geolocation_permission_context.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/geolocation/geolocation_permission_context.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/l10n_util.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "app/resource_bundle.h"
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser.h"
11731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/browser_thread.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extensions_service.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/geolocation/geolocation_dispatcher_host.h"
15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/geolocation/geolocation_provider.h"
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/prefs/pref_service.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/profile.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_process_host.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_view_host.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_view_host_notification_task.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/infobar_delegate.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_util.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/render_messages.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/locale_settings.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class controls the geolocation infobar queue per profile, and it's an
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// internal class to GeolocationPermissionContext.
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// An alternate approach would be to have this queue per tab, and use
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// notifications to broadcast when permission is set / listen to notification to
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// cancel pending requests. This may be specially useful if there are other
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// things listening for such notifications.
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// For the time being this class is self-contained and it doesn't seem pulling
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the notification infrastructure would simplify.
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass GeolocationInfoBarQueueController {
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationInfoBarQueueController(
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GeolocationPermissionContext* geolocation_permission_context,
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Profile* profile);
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~GeolocationInfoBarQueueController();
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The InfoBar will be displayed immediately if the tab is not already
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // displaying one, otherwise it'll be queued.
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CreateInfoBarRequest(
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id,
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const GURL& requesting_frame, const GURL& emebedder);
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancels a specific infobar request.
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CancelInfoBarRequest(
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id);
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called by the InfoBarDelegate to notify it's closed. It'll display a new
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // InfoBar if there's any request pending for this tab.
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnInfoBarClosed(
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id);
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called by the InfoBarDelegate to notify permission has been set.
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It'll notify and dismiss any other pending InfoBar request for the same
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |requesting_frame| and embedder.
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnPermissionSet(
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id,
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const GURL& requesting_frame, const GURL& embedder, bool allowed);
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct PendingInfoBarRequest;
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef std::vector<PendingInfoBarRequest> PendingInfoBarRequests;
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Shows the first pending infobar for this tab.
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ShowQueuedInfoBar(int render_process_id, int render_view_id);
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancels an InfoBar request and returns the next iterator position.
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<PendingInfoBarRequest>::iterator CancelInfoBarRequestInternal(
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::vector<PendingInfoBarRequest>::iterator i);
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationPermissionContext* const geolocation_permission_context_;
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Profile* const profile_;
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Contains all pending infobar requests.
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PendingInfoBarRequests pending_infobar_requests_;
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is the delegate used to display the confirmation info bar.
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationConfirmInfoBarDelegate(
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      TabContents* tab_contents, GeolocationInfoBarQueueController* controller,
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id,
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const GURL& requesting_frame_url,
953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const std::string& display_languages)
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : ConfirmInfoBarDelegate(tab_contents),
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        tab_contents_(tab_contents),
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        controller_(controller),
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        render_process_id_(render_process_id),
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        render_view_id_(render_view_id),
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bridge_id_(bridge_id),
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        requesting_frame_url_(requesting_frame_url),
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        display_languages_(display_languages) {
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ConfirmInfoBarDelegate
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void InfoBarClosed() {
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    controller_->OnInfoBarClosed(render_process_id_, render_view_id_,
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 bridge_id_);
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete this;
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual Type GetInfoBarType() { return PAGE_ACTION_TYPE; }
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool Accept() { return OnPermissionSet(true); }
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool Cancel() { return OnPermissionSet(false); }
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual int GetButtons() const { return BUTTON_OK | BUTTON_CANCEL; }
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual string16 GetButtonLabel(InfoBarButton button) const {
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (button) {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case BUTTON_OK:
1193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return l10n_util::GetStringUTF16(IDS_GEOLOCATION_ALLOW_BUTTON);
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case BUTTON_CANCEL:
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return l10n_util::GetStringUTF16(IDS_GEOLOCATION_DENY_BUTTON);
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      default:
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // All buttons are labeled above.
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED() << "Bad button id " << button;
1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        return string16();
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual string16 GetMessageText() const {
1293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return l10n_util::GetStringFUTF16(
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDS_GEOLOCATION_INFOBAR_QUESTION,
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        net::FormatUrl(requesting_frame_url_.GetOrigin(), display_languages_));
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual SkBitmap* GetIcon() const {
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_GEOLOCATION_INFOBAR_ICON);
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  virtual string16 GetLinkText() {
1383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool LinkClicked(WindowOpenDisposition disposition) {
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Ignore the click dispostion and always open in a new top level tab.
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tab_contents_->OpenURL(
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GURL(l10n_util::GetStringUTF8(IDS_LEARN_MORE_GEOLOCATION_URL)), GURL(),
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NEW_FOREGROUND_TAB, PageTransition::LINK);
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // Do not dismiss the info bar.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool OnPermissionSet(bool confirm) {
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    controller_->OnPermissionSet(
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        render_process_id_, render_view_id_, bridge_id_, requesting_frame_url_,
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        tab_contents_->GetURL(), confirm);
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents_;
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationInfoBarQueueController* controller_;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int render_process_id_;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int render_view_id_;
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int bridge_id_;
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL requesting_frame_url_;
1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string display_languages_;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_IMPLICIT_CONSTRUCTORS(GeolocationConfirmInfoBarDelegate);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct GeolocationInfoBarQueueController::PendingInfoBarRequest {
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int render_process_id;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int render_view_id;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int bridge_id;
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL requesting_frame;
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL embedder;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If non-NULL, it's the current geolocation infobar for this tab.
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InfoBarDelegate* infobar_delegate;
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool IsForTab(int p_render_process_id, int p_render_view_id) const {
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return render_process_id == p_render_process_id &&
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           render_view_id == p_render_view_id;
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool IsForPair(const GURL& p_requesting_frame, const GURL& p_embedder) const {
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return requesting_frame == p_requesting_frame &&
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           embedder == p_embedder;
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool Equals(int p_render_process_id,
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              int p_render_view_id,
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              int p_bridge_id) const {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return IsForTab(p_render_process_id, p_render_view_id) &&
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           bridge_id == p_bridge_id;
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGeolocationInfoBarQueueController::GeolocationInfoBarQueueController(
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GeolocationPermissionContext* geolocation_permission_context,
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile)
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : geolocation_permission_context_(geolocation_permission_context),
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_(profile) {
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGeolocationInfoBarQueueController::~GeolocationInfoBarQueueController() {
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::CreateInfoBarRequest(
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame, const GURL& embedder) {
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This makes sure that no duplicates are added to
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // |pending_infobar_requests_| as an artificial permission request may
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // already exist in the queue as per
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // GeolocationPermissionContext::StartUpdatingRequested
2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // See http://crbug.com/51899 for more details.
2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(joth): Once we have CLIENT_BASED_GEOLOCATION and
2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // WTF_USE_PREEMPT_GEOLOCATION_PERMISSION set in WebKit we should be able to
2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // just use a DCHECK to check if a duplicate is attempting to be added.
2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  while (i != pending_infobar_requests_.end()) {
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (i->Equals(render_process_id, render_view_id, bridge_id)) {
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      // The request already exists.
2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      DCHECK(i->IsForPair(requesting_frame, embedder));
2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      return;
2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ++i;
2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PendingInfoBarRequest pending_infobar_request;
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.render_process_id = render_process_id;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.render_view_id = render_view_id;
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.bridge_id = bridge_id;
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.requesting_frame = requesting_frame;
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.embedder = embedder;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.infobar_delegate = NULL;
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_requests_.push_back(pending_infobar_request);
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ShowQueuedInfoBar(render_process_id, render_view_id);
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::CancelInfoBarRequest(
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id) {
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != pending_infobar_requests_.end(); ++i) {
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i->Equals(render_process_id, render_view_id, bridge_id)) {
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CancelInfoBarRequestInternal(i);
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::OnInfoBarClosed(
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id) {
250731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != pending_infobar_requests_.end(); ++i) {
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i->Equals(render_process_id, render_view_id, bridge_id)) {
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      pending_infobar_requests_.erase(i);
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ShowQueuedInfoBar(render_process_id, render_view_id);
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::OnPermissionSet(
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame, const GURL& embedder, bool allowed) {
264731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Persist the permission.
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ContentSetting content_setting =
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  profile_->GetGeolocationContentSettingsMap()->SetContentSetting(
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      requesting_frame.GetOrigin(), embedder.GetOrigin(), content_setting);
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now notify all pending requests that the permission has been set.
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != pending_infobar_requests_.end();) {
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i->IsForPair(requesting_frame, embedder)) {
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // There was a pending request for the same [frame, embedder].
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (i->Equals(render_process_id, render_view_id, bridge_id)) {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // The request that set permission will be removed by TabContents
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // itself, that is, we should not try to cancel the infobar that has
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // just notified us.
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        i->infobar_delegate = NULL;
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Cancel it first, and then notify the permission.
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Note: if the pending request had an infobar, TabContents will
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // eventually close it and we will pump the queue via OnInfoBarClosed().
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PendingInfoBarRequest other_request = *i;
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      i = CancelInfoBarRequestInternal(i);
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      geolocation_permission_context_->NotifyPermissionSet(
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          other_request.render_process_id, other_request.render_view_id,
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          other_request.bridge_id, other_request.requesting_frame, allowed);
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ++i;
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::ShowQueuedInfoBar(
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id) {
2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  TabContents* tab_contents =
2993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      tab_util::GetTabContentsByID(render_process_id, render_view_id);
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
3013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       i != pending_infobar_requests_.end();) {
3023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!i->IsForTab(render_process_id, render_view_id)) {
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      ++i;
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      continue;
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!tab_contents) {
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      i = pending_infobar_requests_.erase(i);
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      continue;
3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // Check if already displayed.
3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (i->infobar_delegate)
3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      break;
3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    i->infobar_delegate = new GeolocationConfirmInfoBarDelegate(
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        tab_contents, this,
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        render_process_id, render_view_id,
3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        i->bridge_id, i->requesting_frame,
3173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    tab_contents->AddInfoBar(i->infobar_delegate);
3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    break;
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<GeolocationInfoBarQueueController::PendingInfoBarRequest>::iterator
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GeolocationInfoBarQueueController::CancelInfoBarRequestInternal(
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::vector<PendingInfoBarRequest>::iterator i) {
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents =
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_util::GetTabContentsByID(i->render_process_id, i->render_view_id);
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tab_contents && i->infobar_delegate) {
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TabContents will destroy the InfoBar, which will remove from our vector
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // asynchronously.
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tab_contents->RemoveInfoBar(i->infobar_delegate);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ++i;
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Remove it directly from the pending vector.
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return pending_infobar_requests_.erase(i);
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGeolocationPermissionContext::GeolocationPermissionContext(
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile)
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : profile_(profile),
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ALLOW_THIS_IN_INITIALIZER_LIST(
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          geolocation_infobar_queue_controller_(
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             new GeolocationInfoBarQueueController(this, profile))) {
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGeolocationPermissionContext::~GeolocationPermissionContext() {
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::RequestGeolocationPermission(
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame) {
353731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
354731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
355731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::UI, FROM_HERE,
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this,
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            &GeolocationPermissionContext::RequestGeolocationPermission,
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            render_process_id, render_view_id, bridge_id, requesting_frame));
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
361731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExtensionsService* extensions = profile_->GetExtensionsService();
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (extensions) {
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Extension* ext = extensions->GetExtensionByURL(requesting_frame);
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!ext)
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ext = extensions->GetExtensionByWebExtent(requesting_frame);
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ext && ext->HasApiPermission(Extension::kGeolocationPermission)) {
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ExtensionProcessManager* epm = profile_->GetExtensionProcessManager();
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      RenderProcessHost* process = epm->GetExtensionProcess(requesting_frame);
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (process && process->id() == render_process_id) {
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            requesting_frame, true);
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents =
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_util::GetTabContentsByID(render_process_id, render_view_id);
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!tab_contents) {
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The tab may have gone away, or the request may not be from a tab at all.
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(WARNING) << "Attempt to use geolocation tabless renderer: "
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << render_process_id << "," << render_view_id << "," << bridge_id
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << " (can't prompt user without a visible tab)";
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        requesting_frame, false);
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL embedder = tab_contents->GetURL();
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!requesting_frame.is_valid() || !embedder.is_valid()) {
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(WARNING) << "Attempt to use geolocation from an invalid URL: "
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << requesting_frame << "," << embedder
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << " (geolocation is not supported in popups)";
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        requesting_frame, false);
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ContentSetting content_setting =
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_->GetGeolocationContentSettingsMap()->GetContentSetting(
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          requesting_frame, embedder);
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (content_setting == CONTENT_SETTING_BLOCK) {
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        requesting_frame, false);
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (content_setting == CONTENT_SETTING_ALLOW) {
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        requesting_frame, true);
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else { // setting == ask. Prompt the user.
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    geolocation_infobar_queue_controller_->CreateInfoBarRequest(
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        render_process_id, render_view_id, bridge_id, requesting_frame,
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        embedder);
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::CancelGeolocationPermissionRequest(
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame) {
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id);
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
423731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid GeolocationPermissionContext::StartUpdatingRequested(
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame) {
426731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Note we cannot store the arbitrator as a member as it is not thread safe.
428731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  GeolocationProvider* provider = GeolocationProvider::GetInstance();
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WebKit will not request permission until it has received a valid
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // location, but the google network location provider will not give a
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // valid location until the user has granted permission. So we cut the Gordian
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Knot by reusing the the 'start updating' request to also trigger
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a 'permission request' should the provider still be awaiting permission.
435731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!provider->HasPermissionBeenGranted()) {
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    RequestGeolocationPermission(render_process_id, render_view_id, bridge_id,
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 requesting_frame);
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::StopUpdatingRequested(
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id) {
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id);
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::NotifyPermissionSet(
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame, bool allowed) {
449731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents =
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_util::GetTabContentsByID(render_process_id, render_view_id);
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabContents may have gone away (or not exists for extension).
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tab_contents) {
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabSpecificContentSettings* content_settings =
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        tab_contents->GetTabSpecificContentSettings();
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    content_settings->OnGeolocationPermissionSet(requesting_frame.GetOrigin(),
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                 allowed);
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CallRenderViewHost(
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      render_process_id, render_view_id,
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &RenderViewHost::Send,
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new ViewMsg_Geolocation_PermissionSet(render_view_id, bridge_id,
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          allowed));
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (allowed) {
468731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
469731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::IO, FROM_HERE,
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this,
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            &GeolocationPermissionContext::NotifyArbitratorPermissionGranted,
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            requesting_frame));
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::NotifyArbitratorPermissionGranted(
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame) {
478731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
479731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  GeolocationProvider::GetInstance()->OnPermissionGranted(requesting_frame);
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::CancelPendingInfoBarRequest(
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id) {
484731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
485731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BrowserThread::PostTask(
486731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick        BrowserThread::UI, FROM_HERE,
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this,
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            &GeolocationPermissionContext::CancelPendingInfoBarRequest,
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            render_process_id, render_view_id, bridge_id));
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     return;
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
492731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  geolocation_infobar_queue_controller_->CancelInfoBarRequest(
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      render_process_id, render_view_id, bridge_id);
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
496