1 // Copyright (c) 2011 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. 4 5 #include "content/browser/geolocation/geolocation_permission_context.h" 6 7 #include <functional> 8 #include <string> 9 #include <vector> 10 11 #include "base/utf_string_conversions.h" 12 #include "chrome/browser/extensions/extension_service.h" 13 #include "chrome/browser/geolocation/geolocation_content_settings_map.h" 14 #include "chrome/browser/google/google_util.h" 15 #include "chrome/browser/prefs/pref_service.h" 16 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h" 18 #include "chrome/browser/tab_contents/tab_util.h" 19 #include "chrome/common/extensions/extension.h" 20 #include "chrome/common/pref_names.h" 21 #include "content/browser/browser_thread.h" 22 #include "content/browser/geolocation/geolocation_provider.h" 23 #include "content/browser/renderer_host/render_process_host.h" 24 #include "content/browser/renderer_host/render_view_host.h" 25 #include "content/browser/tab_contents/tab_contents.h" 26 #include "content/common/geolocation_messages.h" 27 #include "content/common/notification_registrar.h" 28 #include "content/common/notification_source.h" 29 #include "content/common/notification_type.h" 30 #include "grit/generated_resources.h" 31 #include "grit/locale_settings.h" 32 #include "grit/theme_resources.h" 33 #include "net/base/net_util.h" 34 #include "ui/base/l10n/l10n_util.h" 35 #include "ui/base/resource/resource_bundle.h" 36 37 // GeolocationInfoBarQueueController ------------------------------------------ 38 39 // This class controls the geolocation infobar queue per profile, and it's an 40 // internal class to GeolocationPermissionContext. 41 // An alternate approach would be to have this queue per tab, and use 42 // notifications to broadcast when permission is set / listen to notification to 43 // cancel pending requests. This may be specially useful if there are other 44 // things listening for such notifications. 45 // For the time being this class is self-contained and it doesn't seem pulling 46 // the notification infrastructure would simplify. 47 class GeolocationInfoBarQueueController : NotificationObserver { 48 public: 49 GeolocationInfoBarQueueController( 50 GeolocationPermissionContext* geolocation_permission_context, 51 Profile* profile); 52 ~GeolocationInfoBarQueueController(); 53 54 // The InfoBar will be displayed immediately if the tab is not already 55 // displaying one, otherwise it'll be queued. 56 void CreateInfoBarRequest(int render_process_id, 57 int render_view_id, 58 int bridge_id, 59 const GURL& requesting_frame, 60 const GURL& emebedder); 61 62 // Cancels a specific infobar request. 63 void CancelInfoBarRequest(int render_process_id, 64 int render_view_id, 65 int bridge_id); 66 67 // Called by the InfoBarDelegate to notify it's closed. It'll display a new 68 // InfoBar if there's any request pending for this tab. 69 void OnInfoBarClosed(int render_process_id, 70 int render_view_id, 71 int bridge_id); 72 73 // Called by the InfoBarDelegate to notify permission has been set. 74 // It'll notify and dismiss any other pending InfoBar request for the same 75 // |requesting_frame| and embedder. 76 void OnPermissionSet(int render_process_id, 77 int render_view_id, 78 int bridge_id, 79 const GURL& requesting_frame, 80 const GURL& embedder, 81 bool allowed); 82 83 // NotificationObserver 84 virtual void Observe(NotificationType type, 85 const NotificationSource& source, 86 const NotificationDetails& details); 87 88 private: 89 struct PendingInfoBarRequest; 90 class RequestEquals; 91 92 typedef std::vector<PendingInfoBarRequest> PendingInfoBarRequests; 93 94 // Shows the first pending infobar for this tab. 95 void ShowQueuedInfoBar(int render_process_id, int render_view_id); 96 97 // Cancels an InfoBar request and returns the next iterator position. 98 PendingInfoBarRequests::iterator CancelInfoBarRequestInternal( 99 PendingInfoBarRequests::iterator i); 100 101 NotificationRegistrar registrar_; 102 103 GeolocationPermissionContext* const geolocation_permission_context_; 104 Profile* const profile_; 105 PendingInfoBarRequests pending_infobar_requests_; 106 }; 107 108 109 // GeolocationConfirmInfoBarDelegate ------------------------------------------ 110 111 namespace { 112 113 class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { 114 public: 115 GeolocationConfirmInfoBarDelegate( 116 TabContents* tab_contents, 117 GeolocationInfoBarQueueController* controller, 118 int render_process_id, 119 int render_view_id, 120 int bridge_id, 121 const GURL& requesting_frame_url, 122 const std::string& display_languages); 123 124 private: 125 virtual ~GeolocationConfirmInfoBarDelegate(); 126 127 // ConfirmInfoBarDelegate: 128 virtual void InfoBarClosed(); 129 virtual SkBitmap* GetIcon() const; 130 virtual Type GetInfoBarType() const; 131 virtual string16 GetMessageText() const; 132 virtual string16 GetButtonLabel(InfoBarButton button) const; 133 virtual bool Accept(); 134 virtual bool Cancel(); 135 virtual string16 GetLinkText(); 136 virtual bool LinkClicked(WindowOpenDisposition disposition); 137 138 TabContents* tab_contents_; 139 GeolocationInfoBarQueueController* controller_; 140 int render_process_id_; 141 int render_view_id_; 142 int bridge_id_; 143 GURL requesting_frame_url_; 144 std::string display_languages_; 145 146 DISALLOW_IMPLICIT_CONSTRUCTORS(GeolocationConfirmInfoBarDelegate); 147 }; 148 149 GeolocationConfirmInfoBarDelegate::GeolocationConfirmInfoBarDelegate( 150 TabContents* tab_contents, 151 GeolocationInfoBarQueueController* controller, 152 int render_process_id, 153 int render_view_id, 154 int bridge_id, 155 const GURL& requesting_frame_url, 156 const std::string& display_languages) 157 : ConfirmInfoBarDelegate(tab_contents), 158 tab_contents_(tab_contents), 159 controller_(controller), 160 render_process_id_(render_process_id), 161 render_view_id_(render_view_id), 162 bridge_id_(bridge_id), 163 requesting_frame_url_(requesting_frame_url), 164 display_languages_(display_languages) { 165 } 166 167 GeolocationConfirmInfoBarDelegate::~GeolocationConfirmInfoBarDelegate() { 168 } 169 170 void GeolocationConfirmInfoBarDelegate::InfoBarClosed() { 171 controller_->OnInfoBarClosed(render_process_id_, render_view_id_, 172 bridge_id_); 173 delete this; 174 } 175 176 SkBitmap* GeolocationConfirmInfoBarDelegate::GetIcon() const { 177 return ResourceBundle::GetSharedInstance().GetBitmapNamed( 178 IDR_GEOLOCATION_INFOBAR_ICON); 179 } 180 181 InfoBarDelegate::Type 182 GeolocationConfirmInfoBarDelegate::GetInfoBarType() const { 183 return PAGE_ACTION_TYPE; 184 } 185 186 string16 GeolocationConfirmInfoBarDelegate::GetMessageText() const { 187 return l10n_util::GetStringFUTF16(IDS_GEOLOCATION_INFOBAR_QUESTION, 188 net::FormatUrl(requesting_frame_url_.GetOrigin(), display_languages_)); 189 } 190 191 string16 GeolocationConfirmInfoBarDelegate::GetButtonLabel( 192 InfoBarButton button) const { 193 return l10n_util::GetStringUTF16((button == BUTTON_OK) ? 194 IDS_GEOLOCATION_ALLOW_BUTTON : IDS_GEOLOCATION_DENY_BUTTON); 195 } 196 197 bool GeolocationConfirmInfoBarDelegate::Accept() { 198 controller_->OnPermissionSet(render_process_id_, render_view_id_, bridge_id_, 199 requesting_frame_url_, tab_contents_->GetURL(), true); 200 return true; 201 } 202 203 bool GeolocationConfirmInfoBarDelegate::Cancel() { 204 controller_->OnPermissionSet(render_process_id_, render_view_id_, bridge_id_, 205 requesting_frame_url_, tab_contents_->GetURL(), false); 206 return true; 207 } 208 209 string16 GeolocationConfirmInfoBarDelegate::GetLinkText() { 210 return l10n_util::GetStringUTF16(IDS_LEARN_MORE); 211 } 212 213 bool GeolocationConfirmInfoBarDelegate::LinkClicked( 214 WindowOpenDisposition disposition) { 215 const char kGeolocationLearnMoreUrl[] = 216 #if defined(OS_CHROMEOS) 217 "https://www.google.com/support/chromeos/bin/answer.py?answer=142065"; 218 #else 219 "https://www.google.com/support/chrome/bin/answer.py?answer=142065"; 220 #endif 221 222 // Ignore the click disposition and always open in a new top level tab. 223 tab_contents_->OpenURL( 224 google_util::AppendGoogleLocaleParam(GURL(kGeolocationLearnMoreUrl)), 225 GURL(), NEW_FOREGROUND_TAB, PageTransition::LINK); 226 return false; // Do not dismiss the info bar. 227 } 228 229 } // namespace 230 231 232 // GeolocationInfoBarQueueController::PendingInfoBarRequest ------------------- 233 234 struct GeolocationInfoBarQueueController::PendingInfoBarRequest { 235 public: 236 PendingInfoBarRequest(int render_process_id, 237 int render_view_id, 238 int bridge_id, 239 const GURL& requesting_frame, 240 const GURL& embedder); 241 242 bool IsForTab(int p_render_process_id, int p_render_view_id) const; 243 bool IsForPair(const GURL& p_requesting_frame, 244 const GURL& p_embedder) const; 245 bool Equals(int p_render_process_id, 246 int p_render_view_id, 247 int p_bridge_id) const; 248 249 int render_process_id; 250 int render_view_id; 251 int bridge_id; 252 GURL requesting_frame; 253 GURL embedder; 254 InfoBarDelegate* infobar_delegate; 255 }; 256 257 GeolocationInfoBarQueueController::PendingInfoBarRequest::PendingInfoBarRequest( 258 int render_process_id, 259 int render_view_id, 260 int bridge_id, 261 const GURL& requesting_frame, 262 const GURL& embedder) 263 : render_process_id(render_process_id), 264 render_view_id(render_view_id), 265 bridge_id(bridge_id), 266 requesting_frame(requesting_frame), 267 embedder(embedder), 268 infobar_delegate(NULL) { 269 } 270 271 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForTab( 272 int p_render_process_id, 273 int p_render_view_id) const { 274 return (render_process_id == p_render_process_id) && 275 (render_view_id == p_render_view_id); 276 } 277 278 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForPair( 279 const GURL& p_requesting_frame, 280 const GURL& p_embedder) const { 281 return (requesting_frame == p_requesting_frame) && (embedder == p_embedder); 282 } 283 284 bool GeolocationInfoBarQueueController::PendingInfoBarRequest::Equals( 285 int p_render_process_id, 286 int p_render_view_id, 287 int p_bridge_id) const { 288 return IsForTab(p_render_process_id, p_render_view_id) && 289 (bridge_id == p_bridge_id); 290 } 291 292 293 // GeolocationInfoBarQueueController::RequestEquals --------------------------- 294 295 // Useful predicate for checking PendingInfoBarRequest equality. 296 class GeolocationInfoBarQueueController::RequestEquals 297 : public std::unary_function<PendingInfoBarRequest, bool> { 298 public: 299 RequestEquals(int render_process_id, int render_view_id, int bridge_id); 300 301 bool operator()(const PendingInfoBarRequest& request) const; 302 303 private: 304 int render_process_id_; 305 int render_view_id_; 306 int bridge_id_; 307 }; 308 309 GeolocationInfoBarQueueController::RequestEquals::RequestEquals( 310 int render_process_id, 311 int render_view_id, 312 int bridge_id) 313 : render_process_id_(render_process_id), 314 render_view_id_(render_view_id), 315 bridge_id_(bridge_id) { 316 } 317 318 bool GeolocationInfoBarQueueController::RequestEquals::operator()( 319 const PendingInfoBarRequest& request) const { 320 return request.Equals(render_process_id_, render_view_id_, bridge_id_); 321 } 322 323 324 // GeolocationInfoBarQueueController ------------------------------------------ 325 326 GeolocationInfoBarQueueController::GeolocationInfoBarQueueController( 327 GeolocationPermissionContext* geolocation_permission_context, 328 Profile* profile) 329 : geolocation_permission_context_(geolocation_permission_context), 330 profile_(profile) { 331 } 332 333 GeolocationInfoBarQueueController::~GeolocationInfoBarQueueController() { 334 } 335 336 void GeolocationInfoBarQueueController::CreateInfoBarRequest( 337 int render_process_id, 338 int render_view_id, 339 int bridge_id, 340 const GURL& requesting_frame, 341 const GURL& embedder) { 342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 343 344 // We shouldn't get duplicate requests. 345 DCHECK(std::find_if(pending_infobar_requests_.begin(), 346 pending_infobar_requests_.end(), 347 RequestEquals(render_process_id, render_view_id, bridge_id)) == 348 pending_infobar_requests_.end()); 349 350 pending_infobar_requests_.push_back(PendingInfoBarRequest(render_process_id, 351 render_view_id, bridge_id, requesting_frame, embedder)); 352 ShowQueuedInfoBar(render_process_id, render_view_id); 353 } 354 355 void GeolocationInfoBarQueueController::CancelInfoBarRequest( 356 int render_process_id, 357 int render_view_id, 358 int bridge_id) { 359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 360 361 PendingInfoBarRequests::iterator i = std::find_if( 362 pending_infobar_requests_.begin(), pending_infobar_requests_.end(), 363 RequestEquals(render_process_id, render_view_id, bridge_id)); 364 // TODO(pkasting): Can this conditional become a DCHECK()? 365 if (i != pending_infobar_requests_.end()) 366 CancelInfoBarRequestInternal(i); 367 } 368 369 void GeolocationInfoBarQueueController::OnInfoBarClosed(int render_process_id, 370 int render_view_id, 371 int bridge_id) { 372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 373 374 PendingInfoBarRequests::iterator i = std::find_if( 375 pending_infobar_requests_.begin(), pending_infobar_requests_.end(), 376 RequestEquals(render_process_id, render_view_id, bridge_id)); 377 if (i != pending_infobar_requests_.end()) 378 pending_infobar_requests_.erase(i); 379 380 ShowQueuedInfoBar(render_process_id, render_view_id); 381 } 382 383 void GeolocationInfoBarQueueController::OnPermissionSet( 384 int render_process_id, 385 int render_view_id, 386 int bridge_id, 387 const GURL& requesting_frame, 388 const GURL& embedder, 389 bool allowed) { 390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 391 392 ContentSetting content_setting = 393 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; 394 profile_->GetGeolocationContentSettingsMap()->SetContentSetting( 395 requesting_frame.GetOrigin(), embedder.GetOrigin(), content_setting); 396 397 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); 398 i != pending_infobar_requests_.end(); ) { 399 if (i->IsForPair(requesting_frame, embedder)) { 400 // Cancel this request first, then notify listeners. TODO(pkasting): Why 401 // is this order important? 402 // NOTE: If the pending request had an infobar, TabContents will close it 403 // either synchronously or asynchronously, which will then pump the queue 404 // via OnInfoBarClosed(). 405 PendingInfoBarRequest copied_request = *i; 406 // Don't let CancelInfoBarRequestInternal() call RemoveInfoBar() on the 407 // delegate that's currently calling us. That delegate is in either 408 // Accept() or Cancel(), so its owning InfoBar will call RemoveInfoBar() 409 // later on in this callstack anyway; and if we do it here, and it causes 410 // the delegate to be deleted, our GURL& args will point to garbage and we 411 // may also cause other problems during stack unwinding. 412 if (i->Equals(render_process_id, render_view_id, bridge_id)) 413 i->infobar_delegate = NULL; 414 i = CancelInfoBarRequestInternal(i); 415 416 geolocation_permission_context_->NotifyPermissionSet( 417 copied_request.render_process_id, copied_request.render_view_id, 418 copied_request.bridge_id, copied_request.requesting_frame, allowed); 419 } else { 420 ++i; 421 } 422 } 423 } 424 425 void GeolocationInfoBarQueueController::Observe( 426 NotificationType type, const NotificationSource& source, 427 const NotificationDetails& details) { 428 registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED, 429 source); 430 TabContents* tab_contents = Source<TabContents>(source).ptr(); 431 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); 432 i != pending_infobar_requests_.end();) { 433 if (i->infobar_delegate == NULL && 434 tab_contents == tab_util::GetTabContentsByID(i->render_process_id, 435 i->render_view_id)) { 436 i = pending_infobar_requests_.erase(i); 437 } else { 438 ++i; 439 } 440 } 441 } 442 443 void GeolocationInfoBarQueueController::ShowQueuedInfoBar(int render_process_id, 444 int render_view_id) { 445 TabContents* tab_contents = 446 tab_util::GetTabContentsByID(render_process_id, render_view_id); 447 for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); 448 i != pending_infobar_requests_.end(); ) { 449 if (i->IsForTab(render_process_id, render_view_id)) { 450 if (!tab_contents) { 451 i = pending_infobar_requests_.erase(i); 452 continue; 453 } 454 455 if (!i->infobar_delegate) { 456 if (!registrar_.IsRegistered(this, 457 NotificationType::TAB_CONTENTS_DESTROYED, 458 Source<TabContents>(tab_contents))) { 459 registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, 460 Source<TabContents>(tab_contents)); 461 } 462 i->infobar_delegate = new GeolocationConfirmInfoBarDelegate( 463 tab_contents, this, render_process_id, render_view_id, i->bridge_id, 464 i->requesting_frame, 465 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); 466 tab_contents->AddInfoBar(i->infobar_delegate); 467 } 468 break; 469 } 470 ++i; 471 } 472 } 473 474 GeolocationInfoBarQueueController::PendingInfoBarRequests::iterator 475 GeolocationInfoBarQueueController::CancelInfoBarRequestInternal( 476 PendingInfoBarRequests::iterator i) { 477 InfoBarDelegate* delegate = i->infobar_delegate; 478 if (!delegate) 479 return pending_infobar_requests_.erase(i); 480 481 TabContents* tab_contents = 482 tab_util::GetTabContentsByID(i->render_process_id, i->render_view_id); 483 if (!tab_contents) 484 return pending_infobar_requests_.erase(i); 485 486 // TabContents will destroy the InfoBar, which will remove from our vector 487 // asynchronously. 488 tab_contents->RemoveInfoBar(i->infobar_delegate); 489 return ++i; 490 } 491 492 493 // GeolocationPermissionContext ----------------------------------------------- 494 495 GeolocationPermissionContext::GeolocationPermissionContext( 496 Profile* profile) 497 : profile_(profile), 498 ALLOW_THIS_IN_INITIALIZER_LIST(geolocation_infobar_queue_controller_( 499 new GeolocationInfoBarQueueController(this, profile))) { 500 } 501 502 GeolocationPermissionContext::~GeolocationPermissionContext() { 503 } 504 505 void GeolocationPermissionContext::RequestGeolocationPermission( 506 int render_process_id, int render_view_id, int bridge_id, 507 const GURL& requesting_frame) { 508 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 509 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( 510 this, &GeolocationPermissionContext::RequestGeolocationPermission, 511 render_process_id, render_view_id, bridge_id, requesting_frame)); 512 return; 513 } 514 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 515 516 ExtensionService* extensions = profile_->GetExtensionService(); 517 if (extensions) { 518 const Extension* ext = extensions->GetExtensionByURL(requesting_frame); 519 if (!ext) 520 ext = extensions->GetExtensionByWebExtent(requesting_frame); 521 if (ext && ext->HasApiPermission(Extension::kGeolocationPermission)) { 522 ExtensionProcessManager* epm = profile_->GetExtensionProcessManager(); 523 RenderProcessHost* process = epm->GetExtensionProcess(requesting_frame); 524 if (process && process->id() == render_process_id) { 525 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, 526 requesting_frame, true); 527 return; 528 } 529 } 530 } 531 532 TabContents* tab_contents = 533 tab_util::GetTabContentsByID(render_process_id, render_view_id); 534 if (!tab_contents) { 535 // The tab may have gone away, or the request may not be from a tab at all. 536 LOG(WARNING) << "Attempt to use geolocation tabless renderer: " 537 << render_process_id << "," << render_view_id << "," 538 << bridge_id << " (can't prompt user without a visible tab)"; 539 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, 540 requesting_frame, false); 541 return; 542 } 543 544 GURL embedder = tab_contents->GetURL(); 545 if (!requesting_frame.is_valid() || !embedder.is_valid()) { 546 LOG(WARNING) << "Attempt to use geolocation from an invalid URL: " 547 << requesting_frame << "," << embedder 548 << " (geolocation is not supported in popups)"; 549 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, 550 requesting_frame, false); 551 return; 552 } 553 554 ContentSetting content_setting = 555 profile_->GetGeolocationContentSettingsMap()->GetContentSetting( 556 requesting_frame, embedder); 557 if (content_setting == CONTENT_SETTING_BLOCK) { 558 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, 559 requesting_frame, false); 560 } else if (content_setting == CONTENT_SETTING_ALLOW) { 561 NotifyPermissionSet(render_process_id, render_view_id, bridge_id, 562 requesting_frame, true); 563 } else { // setting == ask. Prompt the user. 564 geolocation_infobar_queue_controller_->CreateInfoBarRequest( 565 render_process_id, render_view_id, bridge_id, requesting_frame, 566 embedder); 567 } 568 } 569 570 void GeolocationPermissionContext::CancelGeolocationPermissionRequest( 571 int render_process_id, 572 int render_view_id, 573 int bridge_id, 574 const GURL& requesting_frame) { 575 CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id); 576 } 577 578 void GeolocationPermissionContext::NotifyPermissionSet( 579 int render_process_id, 580 int render_view_id, 581 int bridge_id, 582 const GURL& requesting_frame, 583 bool allowed) { 584 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 585 586 TabContents* tab_contents = 587 tab_util::GetTabContentsByID(render_process_id, render_view_id); 588 589 // TabContents may have gone away (or not exists for extension). 590 if (tab_contents) { 591 TabSpecificContentSettings* content_settings = 592 tab_contents->GetTabSpecificContentSettings(); 593 content_settings->OnGeolocationPermissionSet(requesting_frame.GetOrigin(), 594 allowed); 595 } 596 597 RenderViewHost* r = RenderViewHost::FromID(render_process_id, render_view_id); 598 if (r) { 599 r->Send(new GeolocationMsg_PermissionSet( 600 render_view_id, bridge_id, allowed)); 601 } 602 603 if (allowed) { 604 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, NewRunnableMethod( 605 this, &GeolocationPermissionContext::NotifyArbitratorPermissionGranted, 606 requesting_frame)); 607 } 608 } 609 610 void GeolocationPermissionContext::NotifyArbitratorPermissionGranted( 611 const GURL& requesting_frame) { 612 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 613 GeolocationProvider::GetInstance()->OnPermissionGranted(requesting_frame); 614 } 615 616 void GeolocationPermissionContext::CancelPendingInfoBarRequest( 617 int render_process_id, 618 int render_view_id, 619 int bridge_id) { 620 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 621 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( 622 this, &GeolocationPermissionContext::CancelPendingInfoBarRequest, 623 render_process_id, render_view_id, bridge_id)); 624 return; 625 } 626 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 627 geolocation_infobar_queue_controller_->CancelInfoBarRequest(render_process_id, 628 render_view_id, bridge_id); 629 } 630