geolocation_permission_context.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
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"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chrome_thread.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extensions_service.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/geolocation/geolocation_dispatcher_host.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/geolocation/location_arbitrator.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/pref_service.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/profile.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_process_host.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_view_host.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/renderer_host/render_view_host_notification_task.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/infobar_delegate.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_contents.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/tab_util.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension.h"
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h"
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/render_messages.h"
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/locale_settings.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class controls the geolocation infobar queue per profile, and it's an
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// internal class to GeolocationPermissionContext.
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// An alternate approach would be to have this queue per tab, and use
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// notifications to broadcast when permission is set / listen to notification to
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// cancel pending requests. This may be specially useful if there are other
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// things listening for such notifications.
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// For the time being this class is self-contained and it doesn't seem pulling
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the notification infrastructure would simplify.
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass GeolocationInfoBarQueueController {
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationInfoBarQueueController(
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GeolocationPermissionContext* geolocation_permission_context,
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      Profile* profile);
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~GeolocationInfoBarQueueController();
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The InfoBar will be displayed immediately if the tab is not already
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // displaying one, otherwise it'll be queued.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CreateInfoBarRequest(
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id,
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const GURL& requesting_frame, const GURL& emebedder);
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancels a specific infobar request.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void CancelInfoBarRequest(
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called by the InfoBarDelegate to notify it's closed. It'll display a new
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // InfoBar if there's any request pending for this tab.
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnInfoBarClosed(
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id);
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Called by the InfoBarDelegate to notify permission has been set.
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // It'll notify and dismiss any other pending InfoBar request for the same
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // |requesting_frame| and embedder.
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void OnPermissionSet(
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id,
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const GURL& requesting_frame, const GURL& embedder, bool allowed);
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct PendingInfoBarRequest;
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef std::vector<PendingInfoBarRequest> PendingInfoBarRequests;
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Shows the first pending infobar for this tab.
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ShowQueuedInfoBar(int render_process_id, int render_view_id);
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Cancels an InfoBar request and returns the next iterator position.
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::vector<PendingInfoBarRequest>::iterator CancelInfoBarRequestInternal(
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::vector<PendingInfoBarRequest>::iterator i);
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationPermissionContext* const geolocation_permission_context_;
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Profile* const profile_;
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Contains all pending infobar requests.
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PendingInfoBarRequests pending_infobar_requests_;
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is the delegate used to display the confirmation info bar.
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationConfirmInfoBarDelegate(
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      TabContents* tab_contents, GeolocationInfoBarQueueController* controller,
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      int render_process_id, int render_view_id, int bridge_id,
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const GURL& requesting_frame_url,
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      const std::wstring& display_languages)
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      : ConfirmInfoBarDelegate(tab_contents),
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        tab_contents_(tab_contents),
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        controller_(controller),
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        render_process_id_(render_process_id),
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        render_view_id_(render_view_id),
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        bridge_id_(bridge_id),
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        requesting_frame_url_(requesting_frame_url),
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        display_languages_(display_languages) {
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ConfirmInfoBarDelegate
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void InfoBarClosed() {
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    controller_->OnInfoBarClosed(render_process_id_, render_view_id_,
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 bridge_id_);
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delete this;
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual Type GetInfoBarType() { return PAGE_ACTION_TYPE; }
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool Accept() { return OnPermissionSet(true); }
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool Cancel() { return OnPermissionSet(false); }
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual int GetButtons() const { return BUTTON_OK | BUTTON_CANCEL; }
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual std::wstring GetButtonLabel(InfoBarButton button) const {
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (button) {
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case BUTTON_OK:
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return l10n_util::GetString(IDS_GEOLOCATION_ALLOW_BUTTON);
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case BUTTON_CANCEL:
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return l10n_util::GetString(IDS_GEOLOCATION_DENY_BUTTON);
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      default:
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // All buttons are labeled above.
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED() << "Bad button id " << button;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return L"";
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual std::wstring GetMessageText() const {
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return l10n_util::GetStringF(
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDS_GEOLOCATION_INFOBAR_QUESTION,
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        net::FormatUrl(requesting_frame_url_.GetOrigin(), display_languages_));
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual SkBitmap* GetIcon() const {
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ResourceBundle::GetSharedInstance().GetBitmapNamed(
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        IDR_GEOLOCATION_INFOBAR_ICON);
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual std::wstring GetLinkText() {
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return l10n_util::GetString(IDS_LEARN_MORE);
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual bool LinkClicked(WindowOpenDisposition disposition) {
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Ignore the click dispostion and always open in a new top level tab.
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tab_contents_->OpenURL(
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GURL(l10n_util::GetStringUTF8(IDS_LEARN_MORE_GEOLOCATION_URL)), GURL(),
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NEW_FOREGROUND_TAB, PageTransition::LINK);
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;  // Do not dismiss the info bar.
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool OnPermissionSet(bool confirm) {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    controller_->OnPermissionSet(
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        render_process_id_, render_view_id_, bridge_id_, requesting_frame_url_,
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        tab_contents_->GetURL(), confirm);
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return true;
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents_;
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationInfoBarQueueController* controller_;
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int render_process_id_;
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int render_view_id_;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int bridge_id_;
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL requesting_frame_url_;
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::wstring display_languages_;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_IMPLICIT_CONSTRUCTORS(GeolocationConfirmInfoBarDelegate);
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstruct GeolocationInfoBarQueueController::PendingInfoBarRequest {
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int render_process_id;
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int render_view_id;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int bridge_id;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL requesting_frame;
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL embedder;
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If non-NULL, it's the current geolocation infobar for this tab.
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InfoBarDelegate* infobar_delegate;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool IsForTab(int p_render_process_id, int p_render_view_id) const {
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return render_process_id == p_render_process_id &&
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           render_view_id == p_render_view_id;
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool IsForPair(const GURL& p_requesting_frame, const GURL& p_embedder) const {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return requesting_frame == p_requesting_frame &&
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           embedder == p_embedder;
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool Equals(int p_render_process_id,
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              int p_render_view_id,
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              int p_bridge_id) const {
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return IsForTab(p_render_process_id, p_render_view_id) &&
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           bridge_id == p_bridge_id;
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGeolocationInfoBarQueueController::GeolocationInfoBarQueueController(
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GeolocationPermissionContext* geolocation_permission_context,
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile)
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : geolocation_permission_context_(geolocation_permission_context),
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_(profile) {
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGeolocationInfoBarQueueController::~GeolocationInfoBarQueueController() {
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::CreateInfoBarRequest(
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame, const GURL& embedder) {
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  PendingInfoBarRequest pending_infobar_request;
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.render_process_id = render_process_id;
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.render_view_id = render_view_id;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.bridge_id = bridge_id;
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.requesting_frame = requesting_frame;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.embedder = embedder;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_request.infobar_delegate = NULL;
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  pending_infobar_requests_.push_back(pending_infobar_request);
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ShowQueuedInfoBar(render_process_id, render_view_id);
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::CancelInfoBarRequest(
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id) {
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != pending_infobar_requests_.end(); ++i) {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i->Equals(render_process_id, render_view_id, bridge_id)) {
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      CancelInfoBarRequestInternal(i);
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::OnInfoBarClosed(
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id) {
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != pending_infobar_requests_.end(); ++i) {
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i->Equals(render_process_id, render_view_id, bridge_id)) {
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      pending_infobar_requests_.erase(i);
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ShowQueuedInfoBar(render_process_id, render_view_id);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::OnPermissionSet(
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame, const GURL& embedder, bool allowed) {
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Persist the permission.
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ContentSetting content_setting =
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  profile_->GetGeolocationContentSettingsMap()->SetContentSetting(
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      requesting_frame.GetOrigin(), embedder.GetOrigin(), content_setting);
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Now notify all pending requests that the permission has been set.
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != pending_infobar_requests_.end();) {
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i->IsForPair(requesting_frame, embedder)) {
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // There was a pending request for the same [frame, embedder].
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (i->Equals(render_process_id, render_view_id, bridge_id)) {
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // The request that set permission will be removed by TabContents
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // itself, that is, we should not try to cancel the infobar that has
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // just notified us.
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        i->infobar_delegate = NULL;
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Cancel it first, and then notify the permission.
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Note: if the pending request had an infobar, TabContents will
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // eventually close it and we will pump the queue via OnInfoBarClosed().
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      PendingInfoBarRequest other_request = *i;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      i = CancelInfoBarRequestInternal(i);
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      geolocation_permission_context_->NotifyPermissionSet(
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          other_request.render_process_id, other_request.render_view_id,
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          other_request.bridge_id, other_request.requesting_frame, allowed);
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ++i;
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationInfoBarQueueController::ShowQueuedInfoBar(
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id) {
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != pending_infobar_requests_.end(); ++i) {
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i->IsForTab(render_process_id, render_view_id)) {
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Check if already displayed.
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (i->infobar_delegate)
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      TabContents* tab_contents =
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          tab_util::GetTabContentsByID(render_process_id, render_view_id);
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      i->infobar_delegate =
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          new GeolocationConfirmInfoBarDelegate(
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              tab_contents, this,
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              render_process_id, render_view_id,
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              i->bridge_id, i->requesting_frame,
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              UTF8ToWide(profile_->GetPrefs()->GetString(
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                  prefs::kAcceptLanguages)));
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_contents->AddInfoBar(i->infobar_delegate);
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::vector<GeolocationInfoBarQueueController::PendingInfoBarRequest>::iterator
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GeolocationInfoBarQueueController::CancelInfoBarRequestInternal(
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::vector<PendingInfoBarRequest>::iterator i) {
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents =
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_util::GetTabContentsByID(i->render_process_id, i->render_view_id);
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tab_contents && i->infobar_delegate) {
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TabContents will destroy the InfoBar, which will remove from our vector
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // asynchronously.
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    tab_contents->RemoveInfoBar(i->infobar_delegate);
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ++i;
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Remove it directly from the pending vector.
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return pending_infobar_requests_.erase(i);
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGeolocationPermissionContext::GeolocationPermissionContext(
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile)
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : profile_(profile),
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ALLOW_THIS_IN_INITIALIZER_LIST(
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          geolocation_infobar_queue_controller_(
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch             new GeolocationInfoBarQueueController(this, profile))) {
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGeolocationPermissionContext::~GeolocationPermissionContext() {
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::RequestGeolocationPermission(
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame) {
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ChromeThread::PostTask(
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ChromeThread::UI, FROM_HERE,
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this,
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            &GeolocationPermissionContext::RequestGeolocationPermission,
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            render_process_id, render_view_id, bridge_id, requesting_frame));
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExtensionsService* extensions = profile_->GetExtensionsService();
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (extensions) {
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Extension* ext = extensions->GetExtensionByURL(requesting_frame);
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!ext)
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ext = extensions->GetExtensionByWebExtent(requesting_frame);
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (ext && ext->HasApiPermission(Extension::kGeolocationPermission)) {
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ExtensionProcessManager* epm = profile_->GetExtensionProcessManager();
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      RenderProcessHost* process = epm->GetExtensionProcess(requesting_frame);
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (process && process->id() == render_process_id) {
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            requesting_frame, true);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents =
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_util::GetTabContentsByID(render_process_id, render_view_id);
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!tab_contents) {
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // The tab may have gone away, or the request may not be from a tab at all.
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(WARNING) << "Attempt to use geolocation tabless renderer: "
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << render_process_id << "," << render_view_id << "," << bridge_id
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << " (can't prompt user without a visible tab)";
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        requesting_frame, false);
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL embedder = tab_contents->GetURL();
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!requesting_frame.is_valid() || !embedder.is_valid()) {
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LOG(WARNING) << "Attempt to use geolocation from an invalid URL: "
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << requesting_frame << "," << embedder
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        << " (geolocation is not supported in popups)";
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        requesting_frame, false);
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ContentSetting content_setting =
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      profile_->GetGeolocationContentSettingsMap()->GetContentSetting(
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          requesting_frame, embedder);
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (content_setting == CONTENT_SETTING_BLOCK) {
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        requesting_frame, false);
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (content_setting == CONTENT_SETTING_ALLOW) {
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    NotifyPermissionSet(render_process_id, render_view_id, bridge_id,
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        requesting_frame, true);
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else { // setting == ask. Prompt the user.
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    geolocation_infobar_queue_controller_->CreateInfoBarRequest(
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        render_process_id, render_view_id, bridge_id, requesting_frame,
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        embedder);
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::CancelGeolocationPermissionRequest(
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame) {
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id);
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGeolocationArbitrator* GeolocationPermissionContext::StartUpdatingRequested(
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame) {
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Note we cannot store the arbitrator as a member as it is not thread safe.
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationArbitrator* arbitrator = GeolocationArbitrator::GetInstance();
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // WebKit will not request permission until it has received a valid
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // location, but the google network location provider will not give a
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // valid location until the user has granted permission. So we cut the Gordian
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Knot by reusing the the 'start updating' request to also trigger
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // a 'permission request' should the provider still be awaiting permission.
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!arbitrator->HasPermissionBeenGranted()) {
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    RequestGeolocationPermission(render_process_id, render_view_id, bridge_id,
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 requesting_frame);
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return arbitrator;
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::StopUpdatingRequested(
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id) {
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id);
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::NotifyPermissionSet(
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id,
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame, bool allowed) {
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents =
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_util::GetTabContentsByID(render_process_id, render_view_id);
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // TabContents may have gone away (or not exists for extension).
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (tab_contents) {
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabSpecificContentSettings* content_settings =
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        tab_contents->GetTabSpecificContentSettings();
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    content_settings->OnGeolocationPermissionSet(requesting_frame.GetOrigin(),
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                 allowed);
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CallRenderViewHost(
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      render_process_id, render_view_id,
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &RenderViewHost::Send,
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      new ViewMsg_Geolocation_PermissionSet(render_view_id, bridge_id,
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          allowed));
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (allowed) {
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ChromeThread::PostTask(
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ChromeThread::IO, FROM_HERE,
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this,
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            &GeolocationPermissionContext::NotifyArbitratorPermissionGranted,
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            requesting_frame));
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::NotifyArbitratorPermissionGranted(
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const GURL& requesting_frame) {
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GeolocationArbitrator::GetInstance()->OnPermissionGranted(requesting_frame);
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GeolocationPermissionContext::CancelPendingInfoBarRequest(
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int render_process_id, int render_view_id, int bridge_id) {
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ChromeThread::PostTask(
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ChromeThread::UI, FROM_HERE,
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NewRunnableMethod(this,
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            &GeolocationPermissionContext::CancelPendingInfoBarRequest,
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            render_process_id, render_view_id, bridge_id));
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch     return;
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  geolocation_infobar_queue_controller_->CancelInfoBarRequest(
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      render_process_id, render_view_id, bridge_id);
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
475