| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/geolocation/chrome_geolocation_permission_context.h" | 5 #include "chrome/browser/geolocation/chrome_geolocation_permission_context.h" |
| 6 | 6 |
| 7 #include <functional> | 7 #include <functional> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/render_view_host.h" | 24 #include "content/public/browser/render_view_host.h" |
| 25 #include "content/public/browser/web_contents.h" | 25 #include "content/public/browser/web_contents.h" |
| 26 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" | 26 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" |
| 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" | 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" |
| 28 | 28 |
| 29 using WebKit::WebSecurityOrigin; | 29 using WebKit::WebSecurityOrigin; |
| 30 using content::BrowserThread; | 30 using content::BrowserThread; |
| 31 using content::WebContents; | 31 using content::WebContents; |
| 32 | 32 |
| 33 | |
| 34 // GeolocationPermissionContext ----------------------------------------------- | 33 // GeolocationPermissionContext ----------------------------------------------- |
| 35 | 34 |
| 36 ChromeGeolocationPermissionContext::ChromeGeolocationPermissionContext( | 35 ChromeGeolocationPermissionContext* ChromeGeolocationPermissionContext::Create( |
| 37 Profile* profile) | 36 Profile* profile) { |
| 38 : profile_(profile), | 37 return new ChromeGeolocationPermissionContext(profile); |
| 39 ALLOW_THIS_IN_INITIALIZER_LIST(geolocation_infobar_queue_controller_( | |
| 40 new GeolocationInfoBarQueueController( | |
| 41 base::Bind( | |
| 42 &ChromeGeolocationPermissionContext::NotifyPermissionSet, | |
| 43 base::Unretained(this)), | |
| 44 profile))) { | |
| 45 } | 38 } |
| 46 | 39 |
| 47 void ChromeGeolocationPermissionContext::RegisterUserPrefs( | 40 void ChromeGeolocationPermissionContext::RegisterUserPrefs( |
| 48 PrefService *user_prefs) { | 41 PrefService *user_prefs) { |
| 49 #if defined(OS_ANDROID) | 42 #if defined(OS_ANDROID) |
| 50 user_prefs->RegisterBooleanPref(prefs::kGeolocationEnabled, true, | 43 user_prefs->RegisterBooleanPref(prefs::kGeolocationEnabled, true, |
| 51 PrefService::UNSYNCABLE_PREF); | 44 PrefService::UNSYNCABLE_PREF); |
| 52 #endif | 45 #endif |
| 53 } | 46 } |
| 54 | 47 |
| 48 ChromeGeolocationPermissionContext::ChromeGeolocationPermissionContext( |
| 49 Profile* profile) |
| 50 : profile_(profile) { |
| 51 } |
| 52 |
| 55 ChromeGeolocationPermissionContext::~ChromeGeolocationPermissionContext() { | 53 ChromeGeolocationPermissionContext::~ChromeGeolocationPermissionContext() { |
| 56 } | 54 } |
| 57 | 55 |
| 58 void ChromeGeolocationPermissionContext::RequestGeolocationPermission( | 56 void ChromeGeolocationPermissionContext::RequestGeolocationPermission( |
| 59 int render_process_id, int render_view_id, int bridge_id, | 57 int render_process_id, int render_view_id, int bridge_id, |
| 60 const GURL& requesting_frame, base::Callback<void(bool)> callback) { | 58 const GURL& requesting_frame, base::Callback<void(bool)> callback) { |
| 61 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 59 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 62 BrowserThread::PostTask( | 60 BrowserThread::PostTask( |
| 63 BrowserThread::UI, FROM_HERE, | 61 BrowserThread::UI, FROM_HERE, |
| 64 base::Bind( | 62 base::Bind( |
| 65 &ChromeGeolocationPermissionContext::RequestGeolocationPermission, | 63 &ChromeGeolocationPermissionContext::RequestGeolocationPermission, |
| 66 this, render_process_id, render_view_id, bridge_id, | 64 this, render_process_id, render_view_id, bridge_id, |
| 67 requesting_frame, callback)); | 65 requesting_frame, callback)); |
| 68 return; | 66 return; |
| 69 } | 67 } |
| 68 |
| 69 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 70 WebContents* web_contents = |
| 71 tab_util::GetWebContentsByID(render_process_id, render_view_id); |
| 72 if (chrome::GetViewType(web_contents) != chrome::VIEW_TYPE_TAB_CONTENTS) { |
| 73 // The tab may have gone away, or the request may not be from a tab at all. |
| 74 // TODO(mpcomplete): the request could be from a background page or |
| 75 // extension popup (tab_contents will have a different ViewType). But why do |
| 76 // we care? Shouldn't we still put an infobar up in the current tab? |
| 77 LOG(WARNING) << "Attempt to use geolocation tabless renderer: " |
| 78 << render_process_id << "," << render_view_id << "," |
| 79 << bridge_id << " (can't prompt user without a visible tab)"; |
| 80 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, |
| 81 requesting_frame, callback, false); |
| 82 return; |
| 83 } |
| 84 |
| 85 GURL embedder = web_contents->GetURL(); |
| 86 if (!requesting_frame.is_valid() || !embedder.is_valid()) { |
| 87 LOG(WARNING) << "Attempt to use geolocation from an invalid URL: " |
| 88 << requesting_frame << "," << embedder |
| 89 << " (geolocation is not supported in popups)"; |
| 90 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, |
| 91 requesting_frame, callback, false); |
| 92 return; |
| 93 } |
| 94 |
| 95 DecidePermission(render_process_id, render_view_id, bridge_id, |
| 96 requesting_frame, embedder, callback); |
| 97 } |
| 98 |
| 99 void ChromeGeolocationPermissionContext::CancelGeolocationPermissionRequest( |
| 100 int render_process_id, |
| 101 int render_view_id, |
| 102 int bridge_id, |
| 103 const GURL& requesting_frame) { |
| 104 CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id); |
| 105 } |
| 106 |
| 107 void ChromeGeolocationPermissionContext::DecidePermission( |
| 108 int render_process_id, int render_view_id, int bridge_id, |
| 109 const GURL& requesting_frame, const GURL& embedder, |
| 110 base::Callback<void(bool)> callback) { |
| 70 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 111 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 71 | 112 |
| 72 #if defined(OS_ANDROID) | 113 #if defined(OS_ANDROID) |
| 73 // Check to see if the feature in its entirety has been disabled. | 114 // Check to see if the feature in its entirety has been disabled. |
| 74 // This must happen before other services (e.g. tabs, extensions) | 115 // This must happen before other services (e.g. tabs, extensions) |
| 75 // get an opportunity to allow the geolocation request. | 116 // get an opportunity to allow the geolocation request. |
| 76 if (!profile_->GetPrefs()->GetBoolean(prefs::kGeolocationEnabled)) { | 117 if (!profile()->GetPrefs()->GetBoolean(prefs::kGeolocationEnabled)) { |
| 77 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, | 118 PermissionDecided(render_process_id, render_view_id, bridge_id, |
| 78 requesting_frame, callback, false); | 119 requesting_frame, embedder, callback, false); |
| 79 return; | 120 return; |
| 80 } | 121 } |
| 81 #endif | 122 #endif |
| 82 | 123 |
| 83 ExtensionService* extension_service = profile_->GetExtensionService(); | 124 ExtensionService* extension_service = profile_->GetExtensionService(); |
| 84 if (extension_service) { | 125 if (extension_service) { |
| 85 const extensions::Extension* extension = | 126 const extensions::Extension* extension = |
| 86 extension_service->extensions()->GetExtensionOrAppByURL( | 127 extension_service->extensions()->GetExtensionOrAppByURL( |
| 87 ExtensionURLInfo( | 128 ExtensionURLInfo( |
| 88 WebSecurityOrigin::createFromString( | 129 WebSecurityOrigin::createFromString( |
| 89 UTF8ToUTF16(requesting_frame.spec())), | 130 UTF8ToUTF16(requesting_frame.spec())), |
| 90 requesting_frame)); | 131 requesting_frame)); |
| 91 if (extension && | 132 if (extension && |
| 92 extension->HasAPIPermission(extensions::APIPermission::kGeolocation)) { | 133 extension->HasAPIPermission(extensions::APIPermission::kGeolocation)) { |
| 93 // Make sure the extension is in the calling process. | 134 // Make sure the extension is in the calling process. |
| 94 if (extension_service->process_map()->Contains( | 135 if (extension_service->process_map()->Contains( |
| 95 extension->id(), render_process_id)) { | 136 extension->id(), render_process_id)) { |
| 96 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, | 137 PermissionDecided(render_process_id, render_view_id, bridge_id, |
| 97 requesting_frame, callback, true); | 138 requesting_frame, embedder, callback, true); |
| 98 return; | 139 return; |
| 99 } | 140 } |
| 100 } | 141 } |
| 101 } | 142 } |
| 102 | 143 |
| 103 WebContents* web_contents = | |
| 104 tab_util::GetWebContentsByID(render_process_id, render_view_id); | |
| 105 if (chrome::GetViewType(web_contents) != chrome::VIEW_TYPE_TAB_CONTENTS) { | |
| 106 // The tab may have gone away, or the request may not be from a tab at all. | |
| 107 // TODO(mpcomplete): the request could be from a background page or | |
| 108 // extension popup (tab_contents will have a different ViewType). But why do | |
| 109 // we care? Shouldn't we still put an infobar up in the current tab? | |
| 110 LOG(WARNING) << "Attempt to use geolocation tabless renderer: " | |
| 111 << render_process_id << "," << render_view_id << "," | |
| 112 << bridge_id << " (can't prompt user without a visible tab)"; | |
| 113 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, | |
| 114 requesting_frame, callback, false); | |
| 115 return; | |
| 116 } | |
| 117 | |
| 118 GURL embedder = web_contents->GetURL(); | |
| 119 if (!requesting_frame.is_valid() || !embedder.is_valid()) { | |
| 120 LOG(WARNING) << "Attempt to use geolocation from an invalid URL: " | |
| 121 << requesting_frame << "," << embedder | |
| 122 << " (geolocation is not supported in popups)"; | |
| 123 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, | |
| 124 requesting_frame, callback, false); | |
| 125 return; | |
| 126 } | |
| 127 | |
| 128 ContentSetting content_setting = | 144 ContentSetting content_setting = |
| 129 profile_->GetHostContentSettingsMap()->GetContentSetting( | 145 profile_->GetHostContentSettingsMap()->GetContentSetting( |
| 130 requesting_frame, | 146 requesting_frame, |
| 131 embedder, | 147 embedder, |
| 132 CONTENT_SETTINGS_TYPE_GEOLOCATION, | 148 CONTENT_SETTINGS_TYPE_GEOLOCATION, |
| 133 std::string()); | 149 std::string()); |
| 134 if (content_setting == CONTENT_SETTING_BLOCK) { | 150 switch (content_setting) { |
| 135 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, | 151 case CONTENT_SETTING_BLOCK: |
| 136 requesting_frame, callback, false); | 152 PermissionDecided(render_process_id, render_view_id, bridge_id, |
| 137 } else if (content_setting == CONTENT_SETTING_ALLOW) { | 153 requesting_frame, embedder, callback, false); |
| 138 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, | 154 break; |
| 139 requesting_frame, callback, true); | 155 case CONTENT_SETTING_ALLOW: |
| 140 } else { // setting == ask. Prompt the user. | 156 PermissionDecided(render_process_id, render_view_id, bridge_id, |
| 141 geolocation_infobar_queue_controller_->CreateInfoBarRequest( | 157 requesting_frame, embedder, callback, true); |
| 142 render_process_id, render_view_id, bridge_id, requesting_frame, | 158 break; |
| 143 embedder, callback); | 159 default: |
| 160 // setting == ask. Prompt the user. |
| 161 QueueController()->CreateInfoBarRequest( |
| 162 render_process_id, render_view_id, bridge_id, requesting_frame, |
| 163 embedder, base::Bind( |
| 164 &ChromeGeolocationPermissionContext::NotifyPermissionSet, |
| 165 base::Unretained(this), |
| 166 render_process_id, render_view_id, bridge_id, requesting_frame, |
| 167 callback)); |
| 144 } | 168 } |
| 145 } | 169 } |
| 146 | 170 |
| 147 void ChromeGeolocationPermissionContext::CancelGeolocationPermissionRequest( | 171 void ChromeGeolocationPermissionContext::PermissionDecided( |
| 148 int render_process_id, | 172 int render_process_id, |
| 149 int render_view_id, | 173 int render_view_id, |
| 150 int bridge_id, | 174 int bridge_id, |
| 151 const GURL& requesting_frame) { | 175 const GURL& requesting_frame, |
| 152 CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id); | 176 const GURL& embedder, |
| 153 } | 177 base::Callback<void(bool)> callback, |
| 154 | 178 bool allowed) { |
| 155 void ChromeGeolocationPermissionContext::CancelPendingInfoBarRequest( | 179 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, |
| 156 int render_process_id, | 180 requesting_frame, callback, allowed); |
| 157 int render_view_id, | |
| 158 int bridge_id) { | |
| 159 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 160 BrowserThread::PostTask( | |
| 161 BrowserThread::UI, FROM_HERE, | |
| 162 base::Bind( | |
| 163 &ChromeGeolocationPermissionContext::CancelPendingInfoBarRequest, | |
| 164 this, render_process_id, render_view_id, bridge_id)); | |
| 165 return; | |
| 166 } | |
| 167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 168 geolocation_infobar_queue_controller_->CancelInfoBarRequest( | |
| 169 render_process_id, | |
| 170 render_view_id, | |
| 171 bridge_id); | |
| 172 } | 181 } |
| 173 | 182 |
| 174 void ChromeGeolocationPermissionContext::NotifyPermissionSet( | 183 void ChromeGeolocationPermissionContext::NotifyPermissionSet( |
| 175 int render_process_id, | 184 int render_process_id, |
| 176 int render_view_id, | 185 int render_view_id, |
| 177 int bridge_id, | 186 int bridge_id, |
| 178 const GURL& requesting_frame, | 187 const GURL& requesting_frame, |
| 179 base::Callback<void(bool)> callback, | 188 base::Callback<void(bool)> callback, |
| 180 bool allowed) { | 189 bool allowed) { |
| 181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 182 | 191 |
| 183 // WebContents may have gone away (or not exists for extension). | 192 // WebContents may have gone away (or not exists for extension). |
| 184 TabSpecificContentSettings* content_settings = | 193 TabSpecificContentSettings* content_settings = |
| 185 TabSpecificContentSettings::Get(render_process_id, render_view_id); | 194 TabSpecificContentSettings::Get(render_process_id, render_view_id); |
| 186 if (content_settings) { | 195 if (content_settings) { |
| 187 content_settings->OnGeolocationPermissionSet(requesting_frame.GetOrigin(), | 196 content_settings->OnGeolocationPermissionSet(requesting_frame.GetOrigin(), |
| 188 allowed); | 197 allowed); |
| 189 } | 198 } |
| 190 | 199 |
| 191 callback.Run(allowed); | 200 callback.Run(allowed); |
| 192 } | 201 } |
| 202 |
| 203 GeolocationInfoBarQueueController* |
| 204 ChromeGeolocationPermissionContext::QueueController() { |
| 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 206 if (!geolocation_infobar_queue_controller_) |
| 207 geolocation_infobar_queue_controller_.reset(CreateQueueController()); |
| 208 return geolocation_infobar_queue_controller_.get(); |
| 209 } |
| 210 |
| 211 GeolocationInfoBarQueueController* |
| 212 ChromeGeolocationPermissionContext::CreateQueueController() { |
| 213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 214 return new GeolocationInfoBarQueueController(profile()); |
| 215 } |
| 216 |
| 217 void ChromeGeolocationPermissionContext::CancelPendingInfoBarRequest( |
| 218 int render_process_id, |
| 219 int render_view_id, |
| 220 int bridge_id) { |
| 221 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 222 BrowserThread::PostTask( |
| 223 BrowserThread::UI, FROM_HERE, |
| 224 base::Bind( |
| 225 &ChromeGeolocationPermissionContext::CancelPendingInfoBarRequest, |
| 226 this, render_process_id, render_view_id, bridge_id)); |
| 227 return; |
| 228 } |
| 229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 230 QueueController()->CancelInfoBarRequest( |
| 231 render_process_id, |
| 232 render_view_id, |
| 233 bridge_id); |
| 234 } |
| OLD | NEW |