Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / geolocation / chrome_geolocation_permission_context.cc
blob01e69ee839d8b4f69ad92b41f9a99e5b9ff9ece3
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/geolocation/chrome_geolocation_permission_context.h"
7 #include <functional>
8 #include <string>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/content_settings/host_content_settings_map.h"
14 #include "chrome/browser/content_settings/permission_request_id.h"
15 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
16 #include "chrome/browser/extensions/suggest_permission_util.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/tab_contents/tab_util.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/browser/web_contents.h"
22 #include "extensions/browser/extension_registry.h"
23 #include "extensions/browser/process_map.h"
24 #include "extensions/browser/view_type_utils.h"
25 #include "extensions/common/extension.h"
27 using extensions::APIPermission;
28 using extensions::ExtensionRegistry;
30 ChromeGeolocationPermissionContext::ChromeGeolocationPermissionContext(
31 Profile* profile)
32 : profile_(profile),
33 shutting_down_(false) {
36 ChromeGeolocationPermissionContext::~ChromeGeolocationPermissionContext() {
37 // ChromeGeolocationPermissionContext may be destroyed on either the UI thread
38 // or the IO thread, but the PermissionQueueController must have been
39 // destroyed on the UI thread.
40 DCHECK(!permission_queue_controller_.get());
43 void ChromeGeolocationPermissionContext::RequestGeolocationPermission(
44 int render_process_id,
45 int render_view_id,
46 int bridge_id,
47 const GURL& requesting_frame,
48 base::Callback<void(bool)> callback) {
49 GURL requesting_frame_origin = requesting_frame.GetOrigin();
50 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
51 content::BrowserThread::PostTask(
52 content::BrowserThread::UI, FROM_HERE,
53 base::Bind(
54 &ChromeGeolocationPermissionContext::RequestGeolocationPermission,
55 this, render_process_id, render_view_id, bridge_id,
56 requesting_frame_origin, callback));
57 return;
60 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
61 if (shutting_down_)
62 return;
64 content::WebContents* web_contents =
65 tab_util::GetWebContentsByID(render_process_id, render_view_id);
66 const PermissionRequestID id(render_process_id, render_view_id, bridge_id, 0);
67 ExtensionRegistry* extension_registry = ExtensionRegistry::Get(profile_);
68 if (extension_registry) {
69 const extensions::Extension* extension =
70 extension_registry->enabled_extensions().GetExtensionOrAppByURL(
71 requesting_frame_origin);
72 if (IsExtensionWithPermissionOrSuggestInConsole(APIPermission::kGeolocation,
73 extension,
74 profile_)) {
75 // Make sure the extension is in the calling process.
76 if (extensions::ProcessMap::Get(profile_)
77 ->Contains(extension->id(), id.render_process_id())) {
78 NotifyPermissionSet(id, requesting_frame_origin, callback, true);
79 return;
84 if (extensions::GetViewType(web_contents) !=
85 extensions::VIEW_TYPE_TAB_CONTENTS) {
86 // The tab may have gone away, or the request may not be from a tab at all.
87 // TODO(mpcomplete): the request could be from a background page or
88 // extension popup (web_contents will have a different ViewType). But why do
89 // we care? Shouldn't we still put an infobar up in the current tab?
90 LOG(WARNING) << "Attempt to use geolocation tabless renderer: "
91 << id.ToString()
92 << " (can't prompt user without a visible tab)";
93 NotifyPermissionSet(id, requesting_frame_origin, callback, false);
94 return;
97 GURL embedder = web_contents->GetLastCommittedURL().GetOrigin();
98 if (!requesting_frame_origin.is_valid() || !embedder.is_valid()) {
99 LOG(WARNING) << "Attempt to use geolocation from an invalid URL: "
100 << requesting_frame_origin << "," << embedder
101 << " (geolocation is not supported in popups)";
102 NotifyPermissionSet(id, requesting_frame_origin, callback, false);
103 return;
106 DecidePermission(id, requesting_frame_origin, embedder, callback);
109 void ChromeGeolocationPermissionContext::CancelGeolocationPermissionRequest(
110 int render_process_id,
111 int render_view_id,
112 int bridge_id,
113 const GURL& requesting_frame) {
114 CancelPendingInfobarRequest(PermissionRequestID(
115 render_process_id, render_view_id, bridge_id, 0));
118 void ChromeGeolocationPermissionContext::DecidePermission(
119 const PermissionRequestID& id,
120 const GURL& requesting_frame,
121 const GURL& embedder,
122 base::Callback<void(bool)> callback) {
123 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
125 ContentSetting content_setting =
126 profile_->GetHostContentSettingsMap()->GetContentSetting(
127 requesting_frame, embedder, CONTENT_SETTINGS_TYPE_GEOLOCATION,
128 std::string());
129 switch (content_setting) {
130 case CONTENT_SETTING_BLOCK:
131 PermissionDecided(id, requesting_frame, embedder, callback, false);
132 break;
133 case CONTENT_SETTING_ALLOW:
134 PermissionDecided(id, requesting_frame, embedder, callback, true);
135 break;
136 default:
137 // setting == ask. Prompt the user.
138 QueueController()->CreateInfoBarRequest(
139 id, requesting_frame, embedder, base::Bind(
140 &ChromeGeolocationPermissionContext::NotifyPermissionSet,
141 base::Unretained(this), id, requesting_frame, callback));
145 void ChromeGeolocationPermissionContext::ShutdownOnUIThread() {
146 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
147 permission_queue_controller_.reset();
148 shutting_down_ = true;
151 void ChromeGeolocationPermissionContext::PermissionDecided(
152 const PermissionRequestID& id,
153 const GURL& requesting_frame,
154 const GURL& embedder,
155 base::Callback<void(bool)> callback,
156 bool allowed) {
157 NotifyPermissionSet(id, requesting_frame, callback, allowed);
160 void ChromeGeolocationPermissionContext::NotifyPermissionSet(
161 const PermissionRequestID& id,
162 const GURL& requesting_frame,
163 base::Callback<void(bool)> callback,
164 bool allowed) {
165 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
167 // WebContents may have gone away (or not exists for extension).
168 TabSpecificContentSettings* content_settings =
169 TabSpecificContentSettings::Get(id.render_process_id(),
170 id.render_view_id());
171 if (content_settings) {
172 content_settings->OnGeolocationPermissionSet(requesting_frame.GetOrigin(),
173 allowed);
176 callback.Run(allowed);
179 PermissionQueueController*
180 ChromeGeolocationPermissionContext::QueueController() {
181 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
182 DCHECK(!shutting_down_);
183 if (!permission_queue_controller_)
184 permission_queue_controller_.reset(CreateQueueController());
185 return permission_queue_controller_.get();
188 PermissionQueueController*
189 ChromeGeolocationPermissionContext::CreateQueueController() {
190 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
191 return new PermissionQueueController(profile(),
192 CONTENT_SETTINGS_TYPE_GEOLOCATION);
195 void ChromeGeolocationPermissionContext::CancelPendingInfobarRequest(
196 const PermissionRequestID& id) {
197 if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
198 content::BrowserThread::PostTask(
199 content::BrowserThread::UI, FROM_HERE,
200 base::Bind(
201 &ChromeGeolocationPermissionContext::CancelPendingInfobarRequest,
202 this, id));
203 return;
205 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
206 if (shutting_down_)
207 return;
208 QueueController()->CancelInfoBarRequest(id);