• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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