1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/geolocation/geolocation_permission_context.h"
6
7 #include <functional>
8 #include <string>
9 #include <vector>
10
11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/geolocation/geolocation_content_settings_map.h"
14 #include "chrome/browser/google/google_util.h"
15 #include "chrome/browser/prefs/pref_service.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
18 #include "chrome/browser/tab_contents/tab_util.h"
19 #include "chrome/common/extensions/extension.h"
20 #include "chrome/common/pref_names.h"
21 #include "content/browser/browser_thread.h"
22 #include "content/browser/geolocation/geolocation_provider.h"
23 #include "content/browser/renderer_host/render_process_host.h"
24 #include "content/browser/renderer_host/render_view_host.h"
25 #include "content/browser/tab_contents/tab_contents.h"
26 #include "content/common/geolocation_messages.h"
27 #include "content/common/notification_registrar.h"
28 #include "content/common/notification_source.h"
29 #include "content/common/notification_type.h"
30 #include "grit/generated_resources.h"
31 #include "grit/locale_settings.h"
32 #include "grit/theme_resources.h"
33 #include "net/base/net_util.h"
34 #include "ui/base/l10n/l10n_util.h"
35 #include "ui/base/resource/resource_bundle.h"
36
37 // GeolocationInfoBarQueueController ------------------------------------------
38
39 // This class controls the geolocation infobar queue per profile, and it's an
40 // internal class to GeolocationPermissionContext.
41 // An alternate approach would be to have this queue per tab, and use
42 // notifications to broadcast when permission is set / listen to notification to
43 // cancel pending requests. This may be specially useful if there are other
44 // things listening for such notifications.
45 // For the time being this class is self-contained and it doesn't seem pulling
46 // the notification infrastructure would simplify.
47 class GeolocationInfoBarQueueController : NotificationObserver {
48 public:
49 GeolocationInfoBarQueueController(
50 GeolocationPermissionContext* geolocation_permission_context,
51 Profile* profile);
52 ~GeolocationInfoBarQueueController();
53
54 // The InfoBar will be displayed immediately if the tab is not already
55 // displaying one, otherwise it'll be queued.
56 void CreateInfoBarRequest(int render_process_id,
57 int render_view_id,
58 int bridge_id,
59 const GURL& requesting_frame,
60 const GURL& emebedder);
61
62 // Cancels a specific infobar request.
63 void CancelInfoBarRequest(int render_process_id,
64 int render_view_id,
65 int bridge_id);
66
67 // Called by the InfoBarDelegate to notify it's closed. It'll display a new
68 // InfoBar if there's any request pending for this tab.
69 void OnInfoBarClosed(int render_process_id,
70 int render_view_id,
71 int bridge_id);
72
73 // Called by the InfoBarDelegate to notify permission has been set.
74 // It'll notify and dismiss any other pending InfoBar request for the same
75 // |requesting_frame| and embedder.
76 void OnPermissionSet(int render_process_id,
77 int render_view_id,
78 int bridge_id,
79 const GURL& requesting_frame,
80 const GURL& embedder,
81 bool allowed);
82
83 // NotificationObserver
84 virtual void Observe(NotificationType type,
85 const NotificationSource& source,
86 const NotificationDetails& details);
87
88 private:
89 struct PendingInfoBarRequest;
90 class RequestEquals;
91
92 typedef std::vector<PendingInfoBarRequest> PendingInfoBarRequests;
93
94 // Shows the first pending infobar for this tab.
95 void ShowQueuedInfoBar(int render_process_id, int render_view_id);
96
97 // Cancels an InfoBar request and returns the next iterator position.
98 PendingInfoBarRequests::iterator CancelInfoBarRequestInternal(
99 PendingInfoBarRequests::iterator i);
100
101 NotificationRegistrar registrar_;
102
103 GeolocationPermissionContext* const geolocation_permission_context_;
104 Profile* const profile_;
105 PendingInfoBarRequests pending_infobar_requests_;
106 };
107
108
109 // GeolocationConfirmInfoBarDelegate ------------------------------------------
110
111 namespace {
112
113 class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
114 public:
115 GeolocationConfirmInfoBarDelegate(
116 TabContents* tab_contents,
117 GeolocationInfoBarQueueController* controller,
118 int render_process_id,
119 int render_view_id,
120 int bridge_id,
121 const GURL& requesting_frame_url,
122 const std::string& display_languages);
123
124 private:
125 virtual ~GeolocationConfirmInfoBarDelegate();
126
127 // ConfirmInfoBarDelegate:
128 virtual void InfoBarClosed();
129 virtual SkBitmap* GetIcon() const;
130 virtual Type GetInfoBarType() const;
131 virtual string16 GetMessageText() const;
132 virtual string16 GetButtonLabel(InfoBarButton button) const;
133 virtual bool Accept();
134 virtual bool Cancel();
135 virtual string16 GetLinkText();
136 virtual bool LinkClicked(WindowOpenDisposition disposition);
137
138 TabContents* tab_contents_;
139 GeolocationInfoBarQueueController* controller_;
140 int render_process_id_;
141 int render_view_id_;
142 int bridge_id_;
143 GURL requesting_frame_url_;
144 std::string display_languages_;
145
146 DISALLOW_IMPLICIT_CONSTRUCTORS(GeolocationConfirmInfoBarDelegate);
147 };
148
GeolocationConfirmInfoBarDelegate(TabContents * tab_contents,GeolocationInfoBarQueueController * controller,int render_process_id,int render_view_id,int bridge_id,const GURL & requesting_frame_url,const std::string & display_languages)149 GeolocationConfirmInfoBarDelegate::GeolocationConfirmInfoBarDelegate(
150 TabContents* tab_contents,
151 GeolocationInfoBarQueueController* controller,
152 int render_process_id,
153 int render_view_id,
154 int bridge_id,
155 const GURL& requesting_frame_url,
156 const std::string& display_languages)
157 : ConfirmInfoBarDelegate(tab_contents),
158 tab_contents_(tab_contents),
159 controller_(controller),
160 render_process_id_(render_process_id),
161 render_view_id_(render_view_id),
162 bridge_id_(bridge_id),
163 requesting_frame_url_(requesting_frame_url),
164 display_languages_(display_languages) {
165 }
166
~GeolocationConfirmInfoBarDelegate()167 GeolocationConfirmInfoBarDelegate::~GeolocationConfirmInfoBarDelegate() {
168 }
169
InfoBarClosed()170 void GeolocationConfirmInfoBarDelegate::InfoBarClosed() {
171 controller_->OnInfoBarClosed(render_process_id_, render_view_id_,
172 bridge_id_);
173 delete this;
174 }
175
GetIcon() const176 SkBitmap* GeolocationConfirmInfoBarDelegate::GetIcon() const {
177 return ResourceBundle::GetSharedInstance().GetBitmapNamed(
178 IDR_GEOLOCATION_INFOBAR_ICON);
179 }
180
181 InfoBarDelegate::Type
GetInfoBarType() const182 GeolocationConfirmInfoBarDelegate::GetInfoBarType() const {
183 return PAGE_ACTION_TYPE;
184 }
185
GetMessageText() const186 string16 GeolocationConfirmInfoBarDelegate::GetMessageText() const {
187 return l10n_util::GetStringFUTF16(IDS_GEOLOCATION_INFOBAR_QUESTION,
188 net::FormatUrl(requesting_frame_url_.GetOrigin(), display_languages_));
189 }
190
GetButtonLabel(InfoBarButton button) const191 string16 GeolocationConfirmInfoBarDelegate::GetButtonLabel(
192 InfoBarButton button) const {
193 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
194 IDS_GEOLOCATION_ALLOW_BUTTON : IDS_GEOLOCATION_DENY_BUTTON);
195 }
196
Accept()197 bool GeolocationConfirmInfoBarDelegate::Accept() {
198 controller_->OnPermissionSet(render_process_id_, render_view_id_, bridge_id_,
199 requesting_frame_url_, tab_contents_->GetURL(), true);
200 return true;
201 }
202
Cancel()203 bool GeolocationConfirmInfoBarDelegate::Cancel() {
204 controller_->OnPermissionSet(render_process_id_, render_view_id_, bridge_id_,
205 requesting_frame_url_, tab_contents_->GetURL(), false);
206 return true;
207 }
208
GetLinkText()209 string16 GeolocationConfirmInfoBarDelegate::GetLinkText() {
210 return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
211 }
212
LinkClicked(WindowOpenDisposition disposition)213 bool GeolocationConfirmInfoBarDelegate::LinkClicked(
214 WindowOpenDisposition disposition) {
215 const char kGeolocationLearnMoreUrl[] =
216 #if defined(OS_CHROMEOS)
217 "https://www.google.com/support/chromeos/bin/answer.py?answer=142065";
218 #else
219 "https://www.google.com/support/chrome/bin/answer.py?answer=142065";
220 #endif
221
222 // Ignore the click disposition and always open in a new top level tab.
223 tab_contents_->OpenURL(
224 google_util::AppendGoogleLocaleParam(GURL(kGeolocationLearnMoreUrl)),
225 GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK);
226 return false; // Do not dismiss the info bar.
227 }
228
229 } // namespace
230
231
232 // GeolocationInfoBarQueueController::PendingInfoBarRequest -------------------
233
234 struct GeolocationInfoBarQueueController::PendingInfoBarRequest {
235 public:
236 PendingInfoBarRequest(int render_process_id,
237 int render_view_id,
238 int bridge_id,
239 const GURL& requesting_frame,
240 const GURL& embedder);
241
242 bool IsForTab(int p_render_process_id, int p_render_view_id) const;
243 bool IsForPair(const GURL& p_requesting_frame,
244 const GURL& p_embedder) const;
245 bool Equals(int p_render_process_id,
246 int p_render_view_id,
247 int p_bridge_id) const;
248
249 int render_process_id;
250 int render_view_id;
251 int bridge_id;
252 GURL requesting_frame;
253 GURL embedder;
254 InfoBarDelegate* infobar_delegate;
255 };
256
PendingInfoBarRequest(int render_process_id,int render_view_id,int bridge_id,const GURL & requesting_frame,const GURL & embedder)257 GeolocationInfoBarQueueController::PendingInfoBarRequest::PendingInfoBarRequest(
258 int render_process_id,
259 int render_view_id,
260 int bridge_id,
261 const GURL& requesting_frame,
262 const GURL& embedder)
263 : render_process_id(render_process_id),
264 render_view_id(render_view_id),
265 bridge_id(bridge_id),
266 requesting_frame(requesting_frame),
267 embedder(embedder),
268 infobar_delegate(NULL) {
269 }
270
IsForTab(int p_render_process_id,int p_render_view_id) const271 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForTab(
272 int p_render_process_id,
273 int p_render_view_id) const {
274 return (render_process_id == p_render_process_id) &&
275 (render_view_id == p_render_view_id);
276 }
277
IsForPair(const GURL & p_requesting_frame,const GURL & p_embedder) const278 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForPair(
279 const GURL& p_requesting_frame,
280 const GURL& p_embedder) const {
281 return (requesting_frame == p_requesting_frame) && (embedder == p_embedder);
282 }
283
Equals(int p_render_process_id,int p_render_view_id,int p_bridge_id) const284 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::Equals(
285 int p_render_process_id,
286 int p_render_view_id,
287 int p_bridge_id) const {
288 return IsForTab(p_render_process_id, p_render_view_id) &&
289 (bridge_id == p_bridge_id);
290 }
291
292
293 // GeolocationInfoBarQueueController::RequestEquals ---------------------------
294
295 // Useful predicate for checking PendingInfoBarRequest equality.
296 class GeolocationInfoBarQueueController::RequestEquals
297 : public std::unary_function<PendingInfoBarRequest, bool> {
298 public:
299 RequestEquals(int render_process_id, int render_view_id, int bridge_id);
300
301 bool operator()(const PendingInfoBarRequest& request) const;
302
303 private:
304 int render_process_id_;
305 int render_view_id_;
306 int bridge_id_;
307 };
308
RequestEquals(int render_process_id,int render_view_id,int bridge_id)309 GeolocationInfoBarQueueController::RequestEquals::RequestEquals(
310 int render_process_id,
311 int render_view_id,
312 int bridge_id)
313 : render_process_id_(render_process_id),
314 render_view_id_(render_view_id),
315 bridge_id_(bridge_id) {
316 }
317
operator ()(const PendingInfoBarRequest & request) const318 bool GeolocationInfoBarQueueController::RequestEquals::operator()(
319 const PendingInfoBarRequest& request) const {
320 return request.Equals(render_process_id_, render_view_id_, bridge_id_);
321 }
322
323
324 // GeolocationInfoBarQueueController ------------------------------------------
325
GeolocationInfoBarQueueController(GeolocationPermissionContext * geolocation_permission_context,Profile * profile)326 GeolocationInfoBarQueueController::GeolocationInfoBarQueueController(
327 GeolocationPermissionContext* geolocation_permission_context,
328 Profile* profile)
329 : geolocation_permission_context_(geolocation_permission_context),
330 profile_(profile) {
331 }
332
~GeolocationInfoBarQueueController()333 GeolocationInfoBarQueueController::~GeolocationInfoBarQueueController() {
334 }
335
CreateInfoBarRequest(int render_process_id,int render_view_id,int bridge_id,const GURL & requesting_frame,const GURL & embedder)336 void GeolocationInfoBarQueueController::CreateInfoBarRequest(
337 int render_process_id,
338 int render_view_id,
339 int bridge_id,
340 const GURL& requesting_frame,
341 const GURL& embedder) {
342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
343
344 // We shouldn't get duplicate requests.
345 DCHECK(std::find_if(pending_infobar_requests_.begin(),
346 pending_infobar_requests_.end(),
347 RequestEquals(render_process_id, render_view_id, bridge_id)) ==
348 pending_infobar_requests_.end());
349
350 pending_infobar_requests_.push_back(PendingInfoBarRequest(render_process_id,
351 render_view_id, bridge_id, requesting_frame, embedder));
352 ShowQueuedInfoBar(render_process_id, render_view_id);
353 }
354
CancelInfoBarRequest(int render_process_id,int render_view_id,int bridge_id)355 void GeolocationInfoBarQueueController::CancelInfoBarRequest(
356 int render_process_id,
357 int render_view_id,
358 int bridge_id) {
359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
360
361 PendingInfoBarRequests::iterator i = std::find_if(
362 pending_infobar_requests_.begin(), pending_infobar_requests_.end(),
363 RequestEquals(render_process_id, render_view_id, bridge_id));
364 // TODO(pkasting): Can this conditional become a DCHECK()?
365 if (i != pending_infobar_requests_.end())
366 CancelInfoBarRequestInternal(i);
367 }
368
OnInfoBarClosed(int render_process_id,int render_view_id,int bridge_id)369 void GeolocationInfoBarQueueController::OnInfoBarClosed(int render_process_id,
370 int render_view_id,
371 int bridge_id) {
372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
373
374 PendingInfoBarRequests::iterator i = std::find_if(
375 pending_infobar_requests_.begin(), pending_infobar_requests_.end(),
376 RequestEquals(render_process_id, render_view_id, bridge_id));
377 if (i != pending_infobar_requests_.end())
378 pending_infobar_requests_.erase(i);
379
380 ShowQueuedInfoBar(render_process_id, render_view_id);
381 }
382
OnPermissionSet(int render_process_id,int render_view_id,int bridge_id,const GURL & requesting_frame,const GURL & embedder,bool allowed)383 void GeolocationInfoBarQueueController::OnPermissionSet(
384 int render_process_id,
385 int render_view_id,
386 int bridge_id,
387 const GURL& requesting_frame,
388 const GURL& embedder,
389 bool allowed) {
390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
391
392 ContentSetting content_setting =
393 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
394 profile_->GetGeolocationContentSettingsMap()->SetContentSetting(
395 requesting_frame.GetOrigin(), embedder.GetOrigin(), content_setting);
396
397 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
398 i != pending_infobar_requests_.end(); ) {
399 if (i->IsForPair(requesting_frame, embedder)) {
400 // Cancel this request first, then notify listeners. TODO(pkasting): Why
401 // is this order important?
402 // NOTE: If the pending request had an infobar, TabContents will close it
403 // either synchronously or asynchronously, which will then pump the queue
404 // via OnInfoBarClosed().
405 PendingInfoBarRequest copied_request = *i;
406 // Don't let CancelInfoBarRequestInternal() call RemoveInfoBar() on the
407 // delegate that's currently calling us. That delegate is in either
408 // Accept() or Cancel(), so its owning InfoBar will call RemoveInfoBar()
409 // later on in this callstack anyway; and if we do it here, and it causes
410 // the delegate to be deleted, our GURL& args will point to garbage and we
411 // may also cause other problems during stack unwinding.
412 if (i->Equals(render_process_id, render_view_id, bridge_id))
413 i->infobar_delegate = NULL;
414 i = CancelInfoBarRequestInternal(i);
415
416 geolocation_permission_context_->NotifyPermissionSet(
417 copied_request.render_process_id, copied_request.render_view_id,
418 copied_request.bridge_id, copied_request.requesting_frame, allowed);
419 } else {
420 ++i;
421 }
422 }
423 }
424
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)425 void GeolocationInfoBarQueueController::Observe(
426 NotificationType type, const NotificationSource& source,
427 const NotificationDetails& details) {
428 registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED,
429 source);
430 TabContents* tab_contents = Source<TabContents>(source).ptr();
431 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
432 i != pending_infobar_requests_.end();) {
433 if (i->infobar_delegate == NULL &&
434 tab_contents == tab_util::GetTabContentsByID(i->render_process_id,
435 i->render_view_id)) {
436 i = pending_infobar_requests_.erase(i);
437 } else {
438 ++i;
439 }
440 }
441 }
442
ShowQueuedInfoBar(int render_process_id,int render_view_id)443 void GeolocationInfoBarQueueController::ShowQueuedInfoBar(int render_process_id,
444 int render_view_id) {
445 TabContents* tab_contents =
446 tab_util::GetTabContentsByID(render_process_id, render_view_id);
447 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
448 i != pending_infobar_requests_.end(); ) {
449 if (i->IsForTab(render_process_id, render_view_id)) {
450 if (!tab_contents) {
451 i = pending_infobar_requests_.erase(i);
452 continue;
453 }
454
455 if (!i->infobar_delegate) {
456 if (!registrar_.IsRegistered(this,
457 NotificationType::TAB_CONTENTS_DESTROYED,
458 Source<TabContents>(tab_contents))) {
459 registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
460 Source<TabContents>(tab_contents));
461 }
462 i->infobar_delegate = new GeolocationConfirmInfoBarDelegate(
463 tab_contents, this, render_process_id, render_view_id, i->bridge_id,
464 i->requesting_frame,
465 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
466 tab_contents->AddInfoBar(i->infobar_delegate);
467 }
468 break;
469 }
470 ++i;
471 }
472 }
473
474 GeolocationInfoBarQueueController::PendingInfoBarRequests::iterator
CancelInfoBarRequestInternal(PendingInfoBarRequests::iterator i)475 GeolocationInfoBarQueueController::CancelInfoBarRequestInternal(
476 PendingInfoBarRequests::iterator i) {
477 InfoBarDelegate* delegate = i->infobar_delegate;
478 if (!delegate)
479 return pending_infobar_requests_.erase(i);
480
481 TabContents* tab_contents =
482 tab_util::GetTabContentsByID(i->render_process_id, i->render_view_id);
483 if (!tab_contents)
484 return pending_infobar_requests_.erase(i);
485
486 // TabContents will destroy the InfoBar, which will remove from our vector
487 // asynchronously.
488 tab_contents->RemoveInfoBar(i->infobar_delegate);
489 return ++i;
490 }
491
492
493 // GeolocationPermissionContext -----------------------------------------------
494
GeolocationPermissionContext(Profile * profile)495 GeolocationPermissionContext::GeolocationPermissionContext(
496 Profile* profile)
497 : profile_(profile),
498 ALLOW_THIS_IN_INITIALIZER_LIST(geolocation_infobar_queue_controller_(
499 new GeolocationInfoBarQueueController(this, profile))) {
500 }
501
~GeolocationPermissionContext()502 GeolocationPermissionContext::~GeolocationPermissionContext() {
503 }
504
RequestGeolocationPermission(int render_process_id,int render_view_id,int bridge_id,const GURL & requesting_frame)505 void GeolocationPermissionContext::RequestGeolocationPermission(
506 int render_process_id, int render_view_id, int bridge_id,
507 const GURL& requesting_frame) {
508 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
509 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
510 this, &GeolocationPermissionContext::RequestGeolocationPermission,
511 render_process_id, render_view_id, bridge_id, requesting_frame));
512 return;
513 }
514 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
515
516 ExtensionService* extensions = profile_->GetExtensionService();
517 if (extensions) {
518 const Extension* ext = extensions->GetExtensionByURL(requesting_frame);
519 if (!ext)
520 ext = extensions->GetExtensionByWebExtent(requesting_frame);
521 if (ext && ext->HasApiPermission(Extension::kGeolocationPermission)) {
522 ExtensionProcessManager* epm = profile_->GetExtensionProcessManager();
523 RenderProcessHost* process = epm->GetExtensionProcess(requesting_frame);
524 if (process && process->id() == render_process_id) {
525 NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
526 requesting_frame, true);
527 return;
528 }
529 }
530 }
531
532 TabContents* tab_contents =
533 tab_util::GetTabContentsByID(render_process_id, render_view_id);
534 if (!tab_contents) {
535 // The tab may have gone away, or the request may not be from a tab at all.
536 LOG(WARNING) << "Attempt to use geolocation tabless renderer: "
537 << render_process_id << "," << render_view_id << ","
538 << bridge_id << " (can't prompt user without a visible tab)";
539 NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
540 requesting_frame, false);
541 return;
542 }
543
544 GURL embedder = tab_contents->GetURL();
545 if (!requesting_frame.is_valid() || !embedder.is_valid()) {
546 LOG(WARNING) << "Attempt to use geolocation from an invalid URL: "
547 << requesting_frame << "," << embedder
548 << " (geolocation is not supported in popups)";
549 NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
550 requesting_frame, false);
551 return;
552 }
553
554 ContentSetting content_setting =
555 profile_->GetGeolocationContentSettingsMap()->GetContentSetting(
556 requesting_frame, embedder);
557 if (content_setting == CONTENT_SETTING_BLOCK) {
558 NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
559 requesting_frame, false);
560 } else if (content_setting == CONTENT_SETTING_ALLOW) {
561 NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
562 requesting_frame, true);
563 } else { // setting == ask. Prompt the user.
564 geolocation_infobar_queue_controller_->CreateInfoBarRequest(
565 render_process_id, render_view_id, bridge_id, requesting_frame,
566 embedder);
567 }
568 }
569
CancelGeolocationPermissionRequest(int render_process_id,int render_view_id,int bridge_id,const GURL & requesting_frame)570 void GeolocationPermissionContext::CancelGeolocationPermissionRequest(
571 int render_process_id,
572 int render_view_id,
573 int bridge_id,
574 const GURL& requesting_frame) {
575 CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id);
576 }
577
NotifyPermissionSet(int render_process_id,int render_view_id,int bridge_id,const GURL & requesting_frame,bool allowed)578 void GeolocationPermissionContext::NotifyPermissionSet(
579 int render_process_id,
580 int render_view_id,
581 int bridge_id,
582 const GURL& requesting_frame,
583 bool allowed) {
584 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
585
586 TabContents* tab_contents =
587 tab_util::GetTabContentsByID(render_process_id, render_view_id);
588
589 // TabContents may have gone away (or not exists for extension).
590 if (tab_contents) {
591 TabSpecificContentSettings* content_settings =
592 tab_contents->GetTabSpecificContentSettings();
593 content_settings->OnGeolocationPermissionSet(requesting_frame.GetOrigin(),
594 allowed);
595 }
596
597 RenderViewHost* r = RenderViewHost::FromID(render_process_id, render_view_id);
598 if (r) {
599 r->Send(new GeolocationMsg_PermissionSet(
600 render_view_id, bridge_id, allowed));
601 }
602
603 if (allowed) {
604 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, NewRunnableMethod(
605 this, &GeolocationPermissionContext::NotifyArbitratorPermissionGranted,
606 requesting_frame));
607 }
608 }
609
NotifyArbitratorPermissionGranted(const GURL & requesting_frame)610 void GeolocationPermissionContext::NotifyArbitratorPermissionGranted(
611 const GURL& requesting_frame) {
612 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
613 GeolocationProvider::GetInstance()->OnPermissionGranted(requesting_frame);
614 }
615
CancelPendingInfoBarRequest(int render_process_id,int render_view_id,int bridge_id)616 void GeolocationPermissionContext::CancelPendingInfoBarRequest(
617 int render_process_id,
618 int render_view_id,
619 int bridge_id) {
620 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
621 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
622 this, &GeolocationPermissionContext::CancelPendingInfoBarRequest,
623 render_process_id, render_view_id, bridge_id));
624 return;
625 }
626 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
627 geolocation_infobar_queue_controller_->CancelInfoBarRequest(render_process_id,
628 render_view_id, bridge_id);
629 }
630