Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 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/geolocation_permission_context.h" | 5 #include "chrome/browser/geolocation/geolocation_permission_context.h" |
| 6 | 6 |
| 7 #include <functional> | |
| 8 #include <string> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/bind.h" | 7 #include "base/bind.h" |
| 12 #include "base/prefs/pref_service.h" | |
| 13 #include "base/strings/utf_string_conversions.h" | |
| 14 #include "chrome/browser/content_settings/host_content_settings_map.h" | |
| 15 #include "chrome/browser/content_settings/permission_request_id.h" | 8 #include "chrome/browser/content_settings/permission_request_id.h" |
| 16 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 9 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 10 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/tab_contents/tab_util.h" | |
| 19 #include "chrome/browser/ui/website_settings/permission_bubble_manager.h" | |
| 20 #include "chrome/browser/ui/website_settings/permission_bubble_request.h" | |
| 21 #include "chrome/common/pref_names.h" | |
| 22 #include "chrome/grit/generated_resources.h" | |
| 23 #include "content/public/browser/browser_thread.h" | 11 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/render_process_host.h" | |
| 25 #include "content/public/browser/render_view_host.h" | |
| 26 #include "content/public/browser/web_contents.h" | 12 #include "content/public/browser/web_contents.h" |
| 27 #include "grit/theme_resources.h" | |
| 28 #include "net/base/net_util.h" | |
| 29 #include "ui/base/l10n/l10n_util.h" | |
| 30 | |
| 31 class GeolocationPermissionRequest : public PermissionBubbleRequest { | |
| 32 public: | |
| 33 GeolocationPermissionRequest(GeolocationPermissionContext* context, | |
| 34 const PermissionRequestID& id, | |
| 35 const GURL& requesting_frame, | |
| 36 const GURL& embedder, | |
| 37 bool user_gesture, | |
| 38 base::Callback<void(bool)> callback, | |
| 39 const std::string& display_languages); | |
| 40 virtual ~GeolocationPermissionRequest(); | |
| 41 | |
| 42 // PermissionBubbleDelegate: | |
| 43 virtual int GetIconID() const OVERRIDE; | |
| 44 virtual base::string16 GetMessageText() const OVERRIDE; | |
| 45 virtual base::string16 GetMessageTextFragment() const OVERRIDE; | |
| 46 virtual bool HasUserGesture() const OVERRIDE; | |
| 47 virtual GURL GetRequestingHostname() const OVERRIDE; | |
| 48 virtual void PermissionGranted() OVERRIDE; | |
| 49 virtual void PermissionDenied() OVERRIDE; | |
| 50 virtual void Cancelled() OVERRIDE; | |
| 51 virtual void RequestFinished() OVERRIDE; | |
| 52 | |
| 53 private: | |
| 54 GeolocationPermissionContext* context_; | |
| 55 PermissionRequestID id_; | |
| 56 GURL requesting_frame_; | |
| 57 GURL embedder_; | |
| 58 bool user_gesture_; | |
| 59 base::Callback<void(bool)> callback_; | |
| 60 std::string display_languages_; | |
| 61 }; | |
| 62 | |
| 63 GeolocationPermissionRequest::GeolocationPermissionRequest( | |
| 64 GeolocationPermissionContext* context, | |
| 65 const PermissionRequestID& id, | |
| 66 const GURL& requesting_frame, | |
| 67 const GURL& embedder, | |
| 68 bool user_gesture, | |
| 69 base::Callback<void(bool)> callback, | |
| 70 const std::string& display_languages) | |
| 71 : context_(context), | |
| 72 id_(id), | |
| 73 requesting_frame_(requesting_frame), | |
| 74 embedder_(embedder), | |
| 75 user_gesture_(user_gesture), | |
| 76 callback_(callback), | |
| 77 display_languages_(display_languages) {} | |
| 78 | |
| 79 GeolocationPermissionRequest::~GeolocationPermissionRequest() {} | |
| 80 | |
| 81 int GeolocationPermissionRequest::GetIconID() const { | |
| 82 return IDR_INFOBAR_GEOLOCATION; | |
| 83 } | |
| 84 | |
| 85 base::string16 GeolocationPermissionRequest::GetMessageText() const { | |
| 86 return l10n_util::GetStringFUTF16( | |
| 87 IDS_GEOLOCATION_INFOBAR_QUESTION, | |
| 88 net::FormatUrl(requesting_frame_.GetOrigin(), display_languages_, | |
| 89 net::kFormatUrlOmitUsernamePassword | | |
| 90 net::kFormatUrlOmitTrailingSlashOnBareHostname, | |
| 91 net::UnescapeRule::SPACES, NULL, NULL, NULL)); | |
| 92 } | |
| 93 | |
| 94 base::string16 GeolocationPermissionRequest::GetMessageTextFragment() const { | |
| 95 return l10n_util::GetStringUTF16(IDS_GEOLOCATION_INFOBAR_PERMISSION_FRAGMENT); | |
| 96 } | |
| 97 | |
| 98 bool GeolocationPermissionRequest::HasUserGesture() const { | |
| 99 return user_gesture_; | |
| 100 } | |
| 101 | |
| 102 GURL GeolocationPermissionRequest::GetRequestingHostname() const { | |
| 103 return requesting_frame_; | |
| 104 } | |
| 105 | |
| 106 void GeolocationPermissionRequest::PermissionGranted() { | |
| 107 context_->QueueController()->UpdateContentSetting( | |
| 108 requesting_frame_, embedder_, true); | |
| 109 context_->NotifyPermissionSet(id_, requesting_frame_, callback_, true); | |
| 110 } | |
| 111 | |
| 112 void GeolocationPermissionRequest::PermissionDenied() { | |
| 113 context_->QueueController()->UpdateContentSetting( | |
| 114 requesting_frame_, embedder_, false); | |
| 115 context_->NotifyPermissionSet(id_, requesting_frame_, callback_, false); | |
| 116 } | |
| 117 | |
| 118 void GeolocationPermissionRequest::Cancelled() { | |
| 119 } | |
| 120 | |
| 121 void GeolocationPermissionRequest::RequestFinished() { | |
| 122 // Deletes 'this'. | |
| 123 context_->RequestFinished(this); | |
| 124 } | |
| 125 | 13 |
| 126 | 14 |
| 127 GeolocationPermissionContext::GeolocationPermissionContext( | 15 GeolocationPermissionContext::GeolocationPermissionContext( |
| 128 Profile* profile) | 16 Profile* profile) |
| 129 : profile_(profile), | 17 : PermissionContextBase(profile, CONTENT_SETTINGS_TYPE_GEOLOCATION), |
| 130 shutting_down_(false), | |
| 131 extensions_context_(profile) { | 18 extensions_context_(profile) { |
| 132 } | 19 } |
| 133 | 20 |
| 134 GeolocationPermissionContext::~GeolocationPermissionContext() { | 21 GeolocationPermissionContext::~GeolocationPermissionContext() { |
| 135 // GeolocationPermissionContext may be destroyed on either the UI thread | |
| 136 // or the IO thread, but the PermissionQueueController must have been | |
| 137 // destroyed on the UI thread. | |
| 138 DCHECK(!permission_queue_controller_.get()); | |
| 139 } | 22 } |
| 140 | 23 |
| 141 void GeolocationPermissionContext::RequestGeolocationPermission( | 24 void GeolocationPermissionContext::RequestPermission( |
| 142 content::WebContents* web_contents, | 25 content::WebContents* web_contents, |
| 143 int bridge_id, | 26 const PermissionRequestID& id, |
| 144 const GURL& requesting_frame, | 27 const GURL& requesting_frame_origin, |
| 145 bool user_gesture, | 28 bool user_gesture, |
| 146 base::Callback<void(bool)> result_callback, | 29 const BrowserPermissionCallback& callback) { |
| 147 base::Closure* cancel_callback) { | 30 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
|
Michael van Ouwerkerk
2014/09/22 17:02:56
DCHECK_CURRENTLY_ON
Miguel Garcia
2014/09/24 11:04:44
Done.
| |
| 148 GURL requesting_frame_origin = requesting_frame.GetOrigin(); | 31 GURL embedder_origin = web_contents->GetLastCommittedURL().GetOrigin(); |
| 149 if (shutting_down_) | |
| 150 return; | |
| 151 | |
| 152 int render_process_id = web_contents->GetRenderProcessHost()->GetID(); | |
| 153 int render_view_id = web_contents->GetRenderViewHost()->GetRoutingID(); | |
| 154 if (cancel_callback) { | |
| 155 *cancel_callback = base::Bind( | |
| 156 &GeolocationPermissionContext::CancelGeolocationPermissionRequest, | |
| 157 this, render_process_id, render_view_id, bridge_id); | |
| 158 } | |
| 159 | |
| 160 const PermissionRequestID id( | |
| 161 render_process_id, render_view_id, bridge_id, GURL()); | |
| 162 | 32 |
| 163 bool permission_set; | 33 bool permission_set; |
| 164 bool new_permission; | 34 bool new_permission; |
| 165 if (extensions_context_.RequestPermission( | 35 if (extensions_context_.RequestPermission( |
| 166 web_contents, id, bridge_id, requesting_frame, user_gesture, | 36 web_contents, id, id.bridge_id(), requesting_frame_origin, user_gesture, |
| 167 result_callback, &permission_set, &new_permission)) { | 37 callback, &permission_set, &new_permission)) { |
| 168 if (permission_set) { | 38 if (permission_set) { |
| 169 NotifyPermissionSet(id, requesting_frame_origin, result_callback, | 39 NotifyPermissionSet(id, requesting_frame_origin, embedder_origin, |
| 170 new_permission); | 40 callback, true, new_permission); |
| 171 } | 41 } |
| 172 return; | 42 return; |
| 173 } | 43 } |
| 174 | 44 |
| 175 GURL embedder = web_contents->GetLastCommittedURL().GetOrigin(); | 45 if (!requesting_frame_origin.is_valid() || !embedder_origin.is_valid()) { |
| 176 if (!requesting_frame_origin.is_valid() || !embedder.is_valid()) { | |
| 177 LOG(WARNING) << "Attempt to use geolocation from an invalid URL: " | 46 LOG(WARNING) << "Attempt to use geolocation from an invalid URL: " |
| 178 << requesting_frame_origin << "," << embedder | 47 << requesting_frame_origin << "," << embedder_origin |
| 179 << " (geolocation is not supported in popups)"; | 48 << " (geolocation is not supported in popups)"; |
| 180 NotifyPermissionSet(id, requesting_frame_origin, result_callback, false); | 49 NotifyPermissionSet(id, requesting_frame_origin, embedder_origin, |
| 50 callback, false /* persist */, false /* allowed */); | |
| 181 return; | 51 return; |
| 182 } | 52 } |
| 183 | 53 |
| 184 DecidePermission(web_contents, id, requesting_frame_origin, user_gesture, | 54 PermissionContextBase::RequestPermission(web_contents, id, |
| 185 embedder, result_callback); | 55 requesting_frame_origin, |
| 56 user_gesture, | |
| 57 callback); | |
| 186 } | 58 } |
| 187 | 59 |
| 188 void GeolocationPermissionContext::CancelGeolocationPermissionRequest( | 60 void GeolocationPermissionContext::CancelPermissionRequest( |
| 189 int render_process_id, | 61 content::WebContents* web_contents, |
| 190 int render_view_id, | 62 const PermissionRequestID& id) { |
| 191 int bridge_id) { | |
| 192 content::WebContents* web_contents = tab_util::GetWebContentsByID( | |
| 193 render_process_id, render_view_id); | |
| 194 if (extensions_context_.CancelPermissionRequest(web_contents, bridge_id)) | |
| 195 return; | |
| 196 | 63 |
| 197 CancelPendingInfobarRequest(PermissionRequestID( | 64 if (extensions_context_.CancelPermissionRequest( |
| 198 render_process_id, render_view_id, bridge_id, GURL())); | 65 web_contents, id.bridge_id())) |
| 66 return; | |
| 67 PermissionContextBase::CancelPermissionRequest(web_contents, id); | |
| 199 } | 68 } |
| 200 | 69 |
| 201 void GeolocationPermissionContext::DecidePermission( | 70 void GeolocationPermissionContext::UpdateTabContext( |
| 202 content::WebContents* web_contents, | |
| 203 const PermissionRequestID& id, | 71 const PermissionRequestID& id, |
| 204 const GURL& requesting_frame, | 72 const GURL& requesting_frame, |
| 205 bool user_gesture, | |
| 206 const GURL& embedder, | |
| 207 base::Callback<void(bool)> callback) { | |
| 208 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 209 | |
| 210 ContentSetting content_setting = | |
| 211 profile_->GetHostContentSettingsMap() | |
| 212 ->GetContentSettingAndMaybeUpdateLastUsage( | |
| 213 requesting_frame, | |
| 214 embedder, | |
| 215 CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
| 216 std::string()); | |
| 217 switch (content_setting) { | |
| 218 case CONTENT_SETTING_BLOCK: | |
| 219 PermissionDecided(id, requesting_frame, embedder, callback, false); | |
| 220 break; | |
| 221 case CONTENT_SETTING_ALLOW: | |
| 222 PermissionDecided(id, requesting_frame, embedder, callback, true); | |
| 223 break; | |
| 224 default: | |
| 225 if (PermissionBubbleManager::Enabled()) { | |
| 226 PermissionBubbleManager* mgr = | |
| 227 PermissionBubbleManager::FromWebContents(web_contents); | |
| 228 if (mgr) { | |
| 229 scoped_ptr<GeolocationPermissionRequest> request_ptr( | |
| 230 new GeolocationPermissionRequest( | |
| 231 this, id, requesting_frame, embedder, user_gesture, callback, | |
| 232 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages))); | |
| 233 GeolocationPermissionRequest* request = request_ptr.get(); | |
| 234 pending_requests_.add(id.ToString(), request_ptr.Pass()); | |
| 235 mgr->AddRequest(request); | |
| 236 } | |
| 237 } else { | |
| 238 // setting == ask. Prompt the user. | |
| 239 QueueController()->CreateInfoBarRequest( | |
| 240 id, requesting_frame, embedder, | |
| 241 base::Bind( | |
| 242 &GeolocationPermissionContext::NotifyPermissionSet, | |
| 243 base::Unretained(this), id, requesting_frame, callback)); | |
| 244 } | |
| 245 } | |
| 246 } | |
| 247 | |
| 248 void GeolocationPermissionContext::CreateInfoBarRequest( | |
| 249 const PermissionRequestID& id, | |
| 250 const GURL& requesting_frame, | |
| 251 const GURL& embedder, | |
| 252 base::Callback<void(bool)> callback) { | |
| 253 QueueController()->CreateInfoBarRequest( | |
| 254 id, requesting_frame, embedder, base::Bind( | |
| 255 &GeolocationPermissionContext::NotifyPermissionSet, | |
| 256 base::Unretained(this), id, requesting_frame, callback)); | |
| 257 } | |
| 258 | |
| 259 void GeolocationPermissionContext::RequestFinished( | |
| 260 GeolocationPermissionRequest* request) { | |
| 261 base::ScopedPtrHashMap<std::string, | |
| 262 GeolocationPermissionRequest>::iterator it; | |
| 263 for (it = pending_requests_.begin(); it != pending_requests_.end(); ++it) { | |
| 264 if (it->second == request) { | |
| 265 pending_requests_.take_and_erase(it); | |
| 266 return; | |
| 267 } | |
| 268 } | |
| 269 } | |
| 270 | |
| 271 | |
| 272 void GeolocationPermissionContext::ShutdownOnUIThread() { | |
| 273 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 274 permission_queue_controller_.reset(); | |
| 275 shutting_down_ = true; | |
| 276 } | |
| 277 | |
| 278 void GeolocationPermissionContext::PermissionDecided( | |
| 279 const PermissionRequestID& id, | |
| 280 const GURL& requesting_frame, | |
| 281 const GURL& embedder, | |
| 282 base::Callback<void(bool)> callback, | |
| 283 bool allowed) { | 73 bool allowed) { |
| 284 NotifyPermissionSet(id, requesting_frame, callback, allowed); | |
| 285 } | |
| 286 | |
| 287 void GeolocationPermissionContext::NotifyPermissionSet( | |
| 288 const PermissionRequestID& id, | |
| 289 const GURL& requesting_frame, | |
| 290 base::Callback<void(bool)> callback, | |
| 291 bool allowed) { | |
| 292 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 293 | |
| 294 // WebContents may have gone away (or not exists for extension). | 74 // WebContents may have gone away (or not exists for extension). |
| 295 TabSpecificContentSettings* content_settings = | 75 TabSpecificContentSettings* content_settings = |
| 296 TabSpecificContentSettings::Get(id.render_process_id(), | 76 TabSpecificContentSettings::Get(id.render_process_id(), |
| 297 id.render_view_id()); | 77 id.render_view_id()); |
| 298 if (content_settings) { | 78 if (content_settings) |
| 299 content_settings->OnGeolocationPermissionSet(requesting_frame.GetOrigin(), | 79 content_settings->OnGeolocationPermissionSet( |
| 300 allowed); | 80 requesting_frame.GetOrigin(), allowed); |
| 301 } | |
| 302 | |
| 303 callback.Run(allowed); | |
| 304 } | 81 } |
| 305 | |
| 306 PermissionQueueController* | |
| 307 GeolocationPermissionContext::QueueController() { | |
| 308 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 309 DCHECK(!shutting_down_); | |
| 310 if (!permission_queue_controller_) | |
| 311 permission_queue_controller_.reset(CreateQueueController()); | |
| 312 return permission_queue_controller_.get(); | |
| 313 } | |
| 314 | |
| 315 PermissionQueueController* | |
| 316 GeolocationPermissionContext::CreateQueueController() { | |
| 317 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 318 return new PermissionQueueController(profile(), | |
| 319 CONTENT_SETTINGS_TYPE_GEOLOCATION); | |
| 320 } | |
| 321 | |
| 322 void GeolocationPermissionContext::CancelPendingInfobarRequest( | |
| 323 const PermissionRequestID& id) { | |
| 324 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 325 if (shutting_down_) | |
| 326 return; | |
| 327 | |
| 328 if (PermissionBubbleManager::Enabled()) { | |
| 329 GeolocationPermissionRequest* cancelling = | |
| 330 pending_requests_.get(id.ToString()); | |
| 331 content::WebContents* web_contents = tab_util::GetWebContentsByID( | |
| 332 id.render_process_id(), id.render_view_id()); | |
| 333 if (cancelling != NULL && web_contents != NULL && | |
| 334 PermissionBubbleManager::FromWebContents(web_contents) != NULL) { | |
| 335 PermissionBubbleManager::FromWebContents(web_contents)-> | |
| 336 CancelRequest(cancelling); | |
| 337 } | |
| 338 return; | |
| 339 } | |
| 340 | |
| 341 QueueController()->CancelInfoBarRequest(id); | |
| 342 } | |
| OLD | NEW |