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. 4 5 #include "chrome/browser/geolocation/chrome_geolocation_permission_context.h" 6 7 #include <set> 8 #include <string> 9 #include <utility> 10 11 #include "base/bind.h" 12 #include "base/containers/hash_tables.h" 13 #include "base/memory/scoped_vector.h" 14 #include "base/synchronization/waitable_event.h" 15 #include "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/content_settings/host_content_settings_map.h" 17 #include "chrome/browser/content_settings/permission_request_id.h" 18 #include "chrome/browser/content_settings/tab_specific_content_settings.h" 19 #include "chrome/browser/geolocation/chrome_geolocation_permission_context_factory.h" 20 #include "chrome/browser/infobars/confirm_infobar_delegate.h" 21 #include "chrome/browser/infobars/infobar.h" 22 #include "chrome/browser/infobars/infobar_service.h" 23 #include "chrome/test/base/chrome_render_view_host_test_harness.h" 24 #include "chrome/test/base/testing_profile.h" 25 #include "content/public/browser/navigation_details.h" 26 #include "content/public/browser/notification_registrar.h" 27 #include "content/public/browser/notification_service.h" 28 #include "content/public/browser/web_contents.h" 29 #include "content/public/test/mock_render_process_host.h" 30 #include "content/public/test/test_renderer_host.h" 31 #include "content/public/test/web_contents_tester.h" 32 #include "extensions/browser/view_type_utils.h" 33 #include "testing/gtest/include/gtest/gtest.h" 34 35 #if defined(OS_ANDROID) 36 #include "base/prefs/pref_service.h" 37 #include "chrome/browser/android/mock_google_location_settings_helper.h" 38 #include "chrome/common/pref_names.h" 39 #endif 40 41 using content::MockRenderProcessHost; 42 43 44 // ClosedInfoBarTracker ------------------------------------------------------- 45 46 // We need to track which infobars were closed. 47 class ClosedInfoBarTracker : public content::NotificationObserver { 48 public: 49 ClosedInfoBarTracker(); 50 virtual ~ClosedInfoBarTracker(); 51 52 // content::NotificationObserver: 53 virtual void Observe(int type, 54 const content::NotificationSource& source, 55 const content::NotificationDetails& details) OVERRIDE; 56 57 size_t size() const { return removed_infobars_.size(); } 58 59 bool Contains(InfoBarDelegate* infobar) const; 60 void Clear(); 61 62 private: 63 FRIEND_TEST_ALL_PREFIXES(GeolocationPermissionContextTests, TabDestroyed); 64 content::NotificationRegistrar registrar_; 65 std::set<InfoBarDelegate*> removed_infobars_; 66 }; 67 68 ClosedInfoBarTracker::ClosedInfoBarTracker() { 69 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, 70 content::NotificationService::AllSources()); 71 } 72 73 ClosedInfoBarTracker::~ClosedInfoBarTracker() { 74 } 75 76 void ClosedInfoBarTracker::Observe( 77 int type, 78 const content::NotificationSource& source, 79 const content::NotificationDetails& details) { 80 DCHECK(type == chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED); 81 removed_infobars_.insert( 82 content::Details<InfoBarRemovedDetails>(details)->first); 83 } 84 85 bool ClosedInfoBarTracker::Contains(InfoBarDelegate* infobar) const { 86 return removed_infobars_.count(infobar) != 0; 87 } 88 89 void ClosedInfoBarTracker::Clear() { 90 removed_infobars_.clear(); 91 } 92 93 94 // GeolocationPermissionContextTests ------------------------------------------ 95 96 // This class sets up GeolocationArbitrator. 97 class GeolocationPermissionContextTests 98 : public ChromeRenderViewHostTestHarness { 99 protected: 100 // ChromeRenderViewHostTestHarness: 101 virtual void SetUp() OVERRIDE; 102 virtual void TearDown() OVERRIDE; 103 104 PermissionRequestID RequestID(int bridge_id); 105 PermissionRequestID RequestIDForTab(int tab, int bridge_id); 106 InfoBarService* infobar_service() { 107 return InfoBarService::FromWebContents(web_contents()); 108 } 109 InfoBarService* infobar_service_for_tab(int tab) { 110 return InfoBarService::FromWebContents(extra_tabs_[tab]); 111 } 112 113 void RequestGeolocationPermission(const PermissionRequestID& id, 114 const GURL& requesting_frame); 115 void CancelGeolocationPermissionRequest(const PermissionRequestID& id, 116 const GURL& requesting_frame); 117 void PermissionResponse(const PermissionRequestID& id, 118 bool allowed); 119 void CheckPermissionMessageSent(int bridge_id, bool allowed); 120 void CheckPermissionMessageSentForTab(int tab, int bridge_id, bool allowed); 121 void CheckPermissionMessageSentInternal(MockRenderProcessHost* process, 122 int bridge_id, 123 bool allowed); 124 void AddNewTab(const GURL& url); 125 void CheckTabContentsState(const GURL& requesting_frame, 126 ContentSetting expected_content_setting); 127 128 scoped_refptr<ChromeGeolocationPermissionContext> 129 geolocation_permission_context_; 130 ClosedInfoBarTracker closed_infobar_tracker_; 131 ScopedVector<content::WebContents> extra_tabs_; 132 133 // A map between renderer child id and a pair represending the bridge id and 134 // whether the requested permission was allowed. 135 base::hash_map<int, std::pair<int, bool> > responses_; 136 }; 137 138 PermissionRequestID GeolocationPermissionContextTests::RequestID( 139 int bridge_id) { 140 return PermissionRequestID( 141 web_contents()->GetRenderProcessHost()->GetID(), 142 web_contents()->GetRenderViewHost()->GetRoutingID(), 143 bridge_id); 144 } 145 146 PermissionRequestID GeolocationPermissionContextTests::RequestIDForTab( 147 int tab, 148 int bridge_id) { 149 return PermissionRequestID( 150 extra_tabs_[tab]->GetRenderProcessHost()->GetID(), 151 extra_tabs_[tab]->GetRenderViewHost()->GetRoutingID(), 152 bridge_id); 153 } 154 155 void GeolocationPermissionContextTests::RequestGeolocationPermission( 156 const PermissionRequestID& id, 157 const GURL& requesting_frame) { 158 geolocation_permission_context_->RequestGeolocationPermission( 159 id.render_process_id(), id.render_view_id(), id.bridge_id(), 160 requesting_frame, 161 base::Bind(&GeolocationPermissionContextTests::PermissionResponse, 162 base::Unretained(this), id)); 163 } 164 165 void GeolocationPermissionContextTests::CancelGeolocationPermissionRequest( 166 const PermissionRequestID& id, 167 const GURL& requesting_frame) { 168 geolocation_permission_context_->CancelGeolocationPermissionRequest( 169 id.render_process_id(), id.render_view_id(), id.bridge_id(), 170 requesting_frame); 171 } 172 173 void GeolocationPermissionContextTests::PermissionResponse( 174 const PermissionRequestID& id, 175 bool allowed) { 176 responses_[id.render_process_id()] = std::make_pair(id.bridge_id(), allowed); 177 } 178 179 void GeolocationPermissionContextTests::CheckPermissionMessageSent( 180 int bridge_id, 181 bool allowed) { 182 CheckPermissionMessageSentInternal(process(), bridge_id, allowed); 183 } 184 185 void GeolocationPermissionContextTests::CheckPermissionMessageSentForTab( 186 int tab, 187 int bridge_id, 188 bool allowed) { 189 CheckPermissionMessageSentInternal(static_cast<MockRenderProcessHost*>( 190 extra_tabs_[tab]->GetRenderProcessHost()), 191 bridge_id, allowed); 192 } 193 194 void GeolocationPermissionContextTests::CheckPermissionMessageSentInternal( 195 MockRenderProcessHost* process, 196 int bridge_id, 197 bool allowed) { 198 ASSERT_EQ(responses_.count(process->GetID()), 1U); 199 EXPECT_EQ(bridge_id, responses_[process->GetID()].first); 200 EXPECT_EQ(allowed, responses_[process->GetID()].second); 201 responses_.erase(process->GetID()); 202 } 203 204 void GeolocationPermissionContextTests::AddNewTab(const GURL& url) { 205 content::WebContents* new_tab = content::WebContents::Create( 206 content::WebContents::CreateParams(profile())); 207 new_tab->GetController().LoadURL( 208 url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string()); 209 content::RenderViewHostTester::For(new_tab->GetRenderViewHost())-> 210 SendNavigate(extra_tabs_.size() + 1, url); 211 212 // Set up required helpers, and make this be as "tabby" as the code requires. 213 extensions::SetViewType(new_tab, extensions::VIEW_TYPE_TAB_CONTENTS); 214 InfoBarService::CreateForWebContents(new_tab); 215 216 extra_tabs_.push_back(new_tab); 217 } 218 219 void GeolocationPermissionContextTests::CheckTabContentsState( 220 const GURL& requesting_frame, 221 ContentSetting expected_content_setting) { 222 TabSpecificContentSettings* content_settings = 223 TabSpecificContentSettings::FromWebContents(web_contents()); 224 const ContentSettingsUsagesState::StateMap& state_map = 225 content_settings->geolocation_usages_state().state_map(); 226 EXPECT_EQ(1U, state_map.count(requesting_frame.GetOrigin())); 227 EXPECT_EQ(0U, state_map.count(requesting_frame)); 228 ContentSettingsUsagesState::StateMap::const_iterator settings = 229 state_map.find(requesting_frame.GetOrigin()); 230 ASSERT_FALSE(settings == state_map.end()) 231 << "geolocation state not found " << requesting_frame; 232 EXPECT_EQ(expected_content_setting, settings->second); 233 } 234 235 void GeolocationPermissionContextTests::SetUp() { 236 ChromeRenderViewHostTestHarness::SetUp(); 237 238 // Set up required helpers, and make this be as "tabby" as the code requires. 239 extensions::SetViewType(web_contents(), extensions::VIEW_TYPE_TAB_CONTENTS); 240 InfoBarService::CreateForWebContents(web_contents()); 241 TabSpecificContentSettings::CreateForWebContents(web_contents()); 242 #if defined(OS_ANDROID) 243 MockGoogleLocationSettingsHelper::SetLocationStatus(true, true); 244 #endif 245 geolocation_permission_context_ = 246 ChromeGeolocationPermissionContextFactory::GetForProfile(profile()); 247 } 248 249 void GeolocationPermissionContextTests::TearDown() { 250 extra_tabs_.clear(); 251 ChromeRenderViewHostTestHarness::TearDown(); 252 } 253 254 // Tests ---------------------------------------------------------------------- 255 256 TEST_F(GeolocationPermissionContextTests, SinglePermission) { 257 GURL requesting_frame("http://www.example.com/geolocation"); 258 NavigateAndCommit(requesting_frame); 259 EXPECT_EQ(0U, infobar_service()->infobar_count()); 260 RequestGeolocationPermission(RequestID(0), requesting_frame); 261 ASSERT_EQ(1U, infobar_service()->infobar_count()); 262 ConfirmInfoBarDelegate* infobar_delegate = 263 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 264 ASSERT_TRUE(infobar_delegate); 265 infobar_delegate->Cancel(); 266 infobar_service()->RemoveInfoBar(infobar_delegate); 267 EXPECT_EQ(1U, closed_infobar_tracker_.size()); 268 EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate)); 269 delete infobar_delegate; 270 } 271 272 #if defined(OS_ANDROID) 273 TEST_F(GeolocationPermissionContextTests, GeolocationEnabledDisabled) { 274 GURL requesting_frame("http://www.example.com/geolocation"); 275 NavigateAndCommit(requesting_frame); 276 MockGoogleLocationSettingsHelper::SetLocationStatus(true, true); 277 EXPECT_EQ(0U, infobar_service()->infobar_count()); 278 RequestGeolocationPermission(RequestID(0), requesting_frame); 279 EXPECT_EQ(1U, infobar_service()->infobar_count()); 280 ConfirmInfoBarDelegate* infobar_delegate_0 = 281 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 282 ASSERT_TRUE(infobar_delegate_0); 283 string16 text_0 = infobar_delegate_0->GetButtonLabel( 284 ConfirmInfoBarDelegate::BUTTON_OK); 285 286 NavigateAndCommit(requesting_frame); 287 MockGoogleLocationSettingsHelper::SetLocationStatus(true, false); 288 EXPECT_EQ(0U, infobar_service()->infobar_count()); 289 RequestGeolocationPermission(RequestID(0), requesting_frame); 290 EXPECT_EQ(1U, infobar_service()->infobar_count()); 291 ConfirmInfoBarDelegate* infobar_delegate_1 = 292 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 293 ASSERT_TRUE(infobar_delegate_1); 294 string16 text_1 = infobar_delegate_1->GetButtonLabel( 295 ConfirmInfoBarDelegate::BUTTON_OK); 296 EXPECT_NE(text_0, text_1); 297 298 NavigateAndCommit(requesting_frame); 299 MockGoogleLocationSettingsHelper::SetLocationStatus(false, false); 300 EXPECT_EQ(0U, infobar_service()->infobar_count()); 301 RequestGeolocationPermission(RequestID(0), requesting_frame); 302 EXPECT_EQ(0U, infobar_service()->infobar_count()); 303 } 304 305 TEST_F(GeolocationPermissionContextTests, MasterEnabledGoogleAppsEnabled) { 306 GURL requesting_frame("http://www.example.com/geolocation"); 307 NavigateAndCommit(requesting_frame); 308 MockGoogleLocationSettingsHelper::SetLocationStatus(true, true); 309 EXPECT_EQ(0U, infobar_service()->infobar_count()); 310 RequestGeolocationPermission(RequestID(0), requesting_frame); 311 EXPECT_EQ(1U, infobar_service()->infobar_count()); 312 ConfirmInfoBarDelegate* infobar_delegate = 313 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 314 ASSERT_TRUE(infobar_delegate); 315 infobar_delegate->Accept(); 316 CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW); 317 CheckPermissionMessageSent(0, true); 318 } 319 320 TEST_F(GeolocationPermissionContextTests, MasterEnabledGoogleAppsDisabled) { 321 GURL requesting_frame("http://www.example.com/geolocation"); 322 NavigateAndCommit(requesting_frame); 323 MockGoogleLocationSettingsHelper::SetLocationStatus(true, false); 324 EXPECT_EQ(0U, infobar_service()->infobar_count()); 325 RequestGeolocationPermission(RequestID(0), requesting_frame); 326 EXPECT_EQ(1U, infobar_service()->infobar_count()); 327 ConfirmInfoBarDelegate* infobar_delegate = 328 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 329 ASSERT_TRUE(infobar_delegate); 330 infobar_delegate->Accept(); 331 EXPECT_TRUE( 332 MockGoogleLocationSettingsHelper::WasGoogleLocationSettingsCalled()); 333 } 334 #endif 335 336 TEST_F(GeolocationPermissionContextTests, QueuedPermission) { 337 GURL requesting_frame_0("http://www.example.com/geolocation"); 338 GURL requesting_frame_1("http://www.example-2.com/geolocation"); 339 EXPECT_EQ(CONTENT_SETTING_ASK, 340 profile()->GetHostContentSettingsMap()->GetContentSetting( 341 requesting_frame_0, requesting_frame_0, 342 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 343 EXPECT_EQ(CONTENT_SETTING_ASK, 344 profile()->GetHostContentSettingsMap()->GetContentSetting( 345 requesting_frame_1, requesting_frame_0, 346 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 347 348 NavigateAndCommit(requesting_frame_0); 349 EXPECT_EQ(0U, infobar_service()->infobar_count()); 350 // Request permission for two frames. 351 RequestGeolocationPermission(RequestID(0), requesting_frame_0); 352 RequestGeolocationPermission(RequestID(1), requesting_frame_1); 353 // Ensure only one infobar is created. 354 ASSERT_EQ(1U, infobar_service()->infobar_count()); 355 ConfirmInfoBarDelegate* infobar_delegate_0 = 356 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 357 ASSERT_TRUE(infobar_delegate_0); 358 string16 text_0 = infobar_delegate_0->GetMessageText(); 359 360 // Accept the first frame. 361 infobar_delegate_0->Accept(); 362 CheckTabContentsState(requesting_frame_0, CONTENT_SETTING_ALLOW); 363 CheckPermissionMessageSent(0, true); 364 365 infobar_service()->RemoveInfoBar(infobar_delegate_0); 366 EXPECT_EQ(1U, closed_infobar_tracker_.size()); 367 EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_0)); 368 closed_infobar_tracker_.Clear(); 369 delete infobar_delegate_0; 370 // Now we should have a new infobar for the second frame. 371 ASSERT_EQ(1U, infobar_service()->infobar_count()); 372 373 ConfirmInfoBarDelegate* infobar_delegate_1 = 374 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 375 ASSERT_TRUE(infobar_delegate_1); 376 string16 text_1 = infobar_delegate_1->GetMessageText(); 377 EXPECT_NE(text_0, text_1); 378 379 // Cancel (block) this frame. 380 infobar_delegate_1->Cancel(); 381 CheckTabContentsState(requesting_frame_1, CONTENT_SETTING_BLOCK); 382 CheckPermissionMessageSent(1, false); 383 infobar_service()->RemoveInfoBar(infobar_delegate_1); 384 EXPECT_EQ(1U, closed_infobar_tracker_.size()); 385 EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_1)); 386 delete infobar_delegate_1; 387 EXPECT_EQ(0U, infobar_service()->infobar_count()); 388 // Ensure the persisted permissions are ok. 389 EXPECT_EQ(CONTENT_SETTING_ALLOW, 390 profile()->GetHostContentSettingsMap()->GetContentSetting( 391 requesting_frame_0, requesting_frame_0, 392 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 393 394 EXPECT_EQ(CONTENT_SETTING_BLOCK, 395 profile()->GetHostContentSettingsMap()->GetContentSetting( 396 requesting_frame_1, requesting_frame_0, 397 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 398 } 399 400 TEST_F(GeolocationPermissionContextTests, PermissionForFileScheme) { 401 GURL requesting_frame("file://example/geolocation.html"); 402 NavigateAndCommit(requesting_frame); 403 EXPECT_EQ(0U, infobar_service()->infobar_count()); 404 RequestGeolocationPermission(RequestID(0), requesting_frame); 405 EXPECT_EQ(1U, infobar_service()->infobar_count()); 406 ConfirmInfoBarDelegate* infobar_delegate = 407 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 408 ASSERT_TRUE(infobar_delegate); 409 // Accept the frame. 410 infobar_delegate->Accept(); 411 CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW); 412 CheckPermissionMessageSent(0, true); 413 infobar_service()->RemoveInfoBar(infobar_delegate); 414 delete infobar_delegate; 415 416 // Make sure the setting is not stored. 417 EXPECT_EQ(CONTENT_SETTING_ASK, 418 profile()->GetHostContentSettingsMap()->GetContentSetting( 419 requesting_frame, 420 requesting_frame, 421 CONTENT_SETTINGS_TYPE_GEOLOCATION, 422 std::string())); 423 } 424 425 TEST_F(GeolocationPermissionContextTests, CancelGeolocationPermissionRequest) { 426 GURL requesting_frame_0("http://www.example.com/geolocation"); 427 GURL requesting_frame_1("http://www.example-2.com/geolocation"); 428 EXPECT_EQ(CONTENT_SETTING_ASK, 429 profile()->GetHostContentSettingsMap()->GetContentSetting( 430 requesting_frame_0, requesting_frame_0, 431 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 432 433 EXPECT_EQ(CONTENT_SETTING_ASK, 434 profile()->GetHostContentSettingsMap()->GetContentSetting( 435 requesting_frame_1, requesting_frame_0, 436 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 437 438 NavigateAndCommit(requesting_frame_0); 439 EXPECT_EQ(0U, infobar_service()->infobar_count()); 440 // Request permission for two frames. 441 RequestGeolocationPermission(RequestID(0), requesting_frame_0); 442 RequestGeolocationPermission(RequestID(1), requesting_frame_1); 443 ASSERT_EQ(1U, infobar_service()->infobar_count()); 444 445 ConfirmInfoBarDelegate* infobar_delegate_0 = 446 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 447 ASSERT_TRUE(infobar_delegate_0); 448 string16 text_0 = infobar_delegate_0->GetMessageText(); 449 450 // Simulate the frame going away, ensure the infobar for this frame 451 // is removed and the next pending infobar is created. 452 CancelGeolocationPermissionRequest(RequestID(0), requesting_frame_0); 453 EXPECT_EQ(1U, closed_infobar_tracker_.size()); 454 EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_0)); 455 closed_infobar_tracker_.Clear(); 456 delete infobar_delegate_0; 457 ASSERT_EQ(1U, infobar_service()->infobar_count()); 458 459 ConfirmInfoBarDelegate* infobar_delegate_1 = 460 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 461 ASSERT_TRUE(infobar_delegate_1); 462 string16 text_1 = infobar_delegate_1->GetMessageText(); 463 EXPECT_NE(text_0, text_1); 464 465 // Allow this frame. 466 infobar_delegate_1->Accept(); 467 CheckTabContentsState(requesting_frame_1, CONTENT_SETTING_ALLOW); 468 CheckPermissionMessageSent(1, true); 469 infobar_service()->RemoveInfoBar(infobar_delegate_1); 470 EXPECT_EQ(1U, closed_infobar_tracker_.size()); 471 EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_1)); 472 delete infobar_delegate_1; 473 EXPECT_EQ(0U, infobar_service()->infobar_count()); 474 // Ensure the persisted permissions are ok. 475 EXPECT_EQ(CONTENT_SETTING_ASK, 476 profile()->GetHostContentSettingsMap()->GetContentSetting( 477 requesting_frame_0, requesting_frame_0, 478 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 479 480 EXPECT_EQ(CONTENT_SETTING_ALLOW, 481 profile()->GetHostContentSettingsMap()->GetContentSetting( 482 requesting_frame_1, requesting_frame_0, 483 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 484 } 485 486 TEST_F(GeolocationPermissionContextTests, InvalidURL) { 487 GURL invalid_embedder("about:blank"); 488 GURL requesting_frame; 489 NavigateAndCommit(invalid_embedder); 490 EXPECT_EQ(0U, infobar_service()->infobar_count()); 491 RequestGeolocationPermission(RequestID(0), requesting_frame); 492 EXPECT_EQ(0U, infobar_service()->infobar_count()); 493 CheckPermissionMessageSent(0, false); 494 } 495 496 TEST_F(GeolocationPermissionContextTests, SameOriginMultipleTabs) { 497 GURL url_a("http://www.example.com/geolocation"); 498 GURL url_b("http://www.example-2.com/geolocation"); 499 NavigateAndCommit(url_a); 500 AddNewTab(url_b); 501 AddNewTab(url_a); 502 503 EXPECT_EQ(0U, infobar_service()->infobar_count()); 504 RequestGeolocationPermission(RequestID(0), url_a); 505 ASSERT_EQ(1U, infobar_service()->infobar_count()); 506 507 RequestGeolocationPermission(RequestIDForTab(0, 0), url_b); 508 EXPECT_EQ(1U, infobar_service_for_tab(0)->infobar_count()); 509 510 RequestGeolocationPermission(RequestIDForTab(1, 0), url_a); 511 ASSERT_EQ(1U, infobar_service_for_tab(1)->infobar_count()); 512 513 ConfirmInfoBarDelegate* removed_infobar = 514 infobar_service_for_tab(1)->infobar_at(0)->AsConfirmInfoBarDelegate(); 515 516 // Accept the first tab. 517 ConfirmInfoBarDelegate* infobar_delegate_0 = 518 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 519 ASSERT_TRUE(infobar_delegate_0); 520 infobar_delegate_0->Accept(); 521 CheckPermissionMessageSent(0, true); 522 infobar_service()->RemoveInfoBar(infobar_delegate_0); 523 EXPECT_EQ(2U, closed_infobar_tracker_.size()); 524 EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_0)); 525 delete infobar_delegate_0; 526 // Now the infobar for the tab with the same origin should have gone. 527 EXPECT_EQ(0U, infobar_service_for_tab(1)->infobar_count()); 528 CheckPermissionMessageSentForTab(1, 0, true); 529 EXPECT_TRUE(closed_infobar_tracker_.Contains(removed_infobar)); 530 closed_infobar_tracker_.Clear(); 531 // Destroy the infobar that has just been removed. 532 delete removed_infobar; 533 534 // But the other tab should still have the info bar... 535 ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count()); 536 ConfirmInfoBarDelegate* infobar_delegate_1 = 537 infobar_service_for_tab(0)->infobar_at(0)->AsConfirmInfoBarDelegate(); 538 infobar_delegate_1->Cancel(); 539 infobar_service_for_tab(0)->RemoveInfoBar(infobar_delegate_1); 540 EXPECT_EQ(1U, closed_infobar_tracker_.size()); 541 EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_1)); 542 delete infobar_delegate_1; 543 } 544 545 TEST_F(GeolocationPermissionContextTests, QueuedOriginMultipleTabs) { 546 GURL url_a("http://www.example.com/geolocation"); 547 GURL url_b("http://www.example-2.com/geolocation"); 548 NavigateAndCommit(url_a); 549 AddNewTab(url_a); 550 551 EXPECT_EQ(0U, infobar_service()->infobar_count()); 552 RequestGeolocationPermission(RequestID(0), url_a); 553 ASSERT_EQ(1U, infobar_service()->infobar_count()); 554 555 RequestGeolocationPermission(RequestIDForTab(0, 0), url_a); 556 EXPECT_EQ(1U, infobar_service_for_tab(0)->infobar_count()); 557 558 RequestGeolocationPermission(RequestIDForTab(0, 1), url_b); 559 ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count()); 560 561 ConfirmInfoBarDelegate* removed_infobar = 562 infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate(); 563 564 // Accept the second tab. 565 ConfirmInfoBarDelegate* infobar_delegate_0 = 566 infobar_service_for_tab(0)->infobar_at(0)->AsConfirmInfoBarDelegate(); 567 ASSERT_TRUE(infobar_delegate_0); 568 infobar_delegate_0->Accept(); 569 CheckPermissionMessageSentForTab(0, 0, true); 570 infobar_service_for_tab(0)->RemoveInfoBar(infobar_delegate_0); 571 EXPECT_EQ(2U, closed_infobar_tracker_.size()); 572 EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_0)); 573 delete infobar_delegate_0; 574 // Now the infobar for the tab with the same origin should have gone. 575 EXPECT_EQ(0U, infobar_service()->infobar_count()); 576 CheckPermissionMessageSent(0, true); 577 EXPECT_TRUE(closed_infobar_tracker_.Contains(removed_infobar)); 578 closed_infobar_tracker_.Clear(); 579 delete removed_infobar; 580 581 // And we should have the queued infobar displayed now. 582 ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count()); 583 584 // Accept the second infobar. 585 ConfirmInfoBarDelegate* infobar_delegate_1 = 586 infobar_service_for_tab(0)->infobar_at(0)->AsConfirmInfoBarDelegate(); 587 ASSERT_TRUE(infobar_delegate_1); 588 infobar_delegate_1->Accept(); 589 CheckPermissionMessageSentForTab(0, 1, true); 590 infobar_service_for_tab(0)->RemoveInfoBar(infobar_delegate_1); 591 EXPECT_EQ(1U, closed_infobar_tracker_.size()); 592 EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_1)); 593 delete infobar_delegate_1; 594 } 595 596 TEST_F(GeolocationPermissionContextTests, TabDestroyed) { 597 GURL requesting_frame_0("http://www.example.com/geolocation"); 598 GURL requesting_frame_1("http://www.example-2.com/geolocation"); 599 EXPECT_EQ(CONTENT_SETTING_ASK, 600 profile()->GetHostContentSettingsMap()->GetContentSetting( 601 requesting_frame_0, requesting_frame_0, 602 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 603 604 EXPECT_EQ(CONTENT_SETTING_ASK, 605 profile()->GetHostContentSettingsMap()->GetContentSetting( 606 requesting_frame_1, requesting_frame_0, 607 CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string())); 608 609 NavigateAndCommit(requesting_frame_0); 610 EXPECT_EQ(0U, infobar_service()->infobar_count()); 611 // Request permission for two frames. 612 RequestGeolocationPermission(RequestID(0), requesting_frame_0); 613 RequestGeolocationPermission(RequestID(1), requesting_frame_1); 614 // Ensure only one infobar is created. 615 ASSERT_EQ(1U, infobar_service()->infobar_count()); 616 InfoBarDelegate* infobar = infobar_service()->infobar_at(0); 617 618 // Delete the tab contents. 619 DeleteContents(); 620 delete infobar; 621 622 // During contents destruction, the infobar will have been closed, and the 623 // pending request should have been cleared without an infobar being created. 624 ASSERT_EQ(1U, closed_infobar_tracker_.size()); 625 ASSERT_TRUE(closed_infobar_tracker_.Contains(infobar)); 626 } 627 628 TEST_F(GeolocationPermissionContextTests, InfoBarUsesCommittedEntry) { 629 GURL requesting_frame_0("http://www.example.com/geolocation"); 630 GURL requesting_frame_1("http://www.example-2.com/geolocation"); 631 NavigateAndCommit(requesting_frame_0); 632 NavigateAndCommit(requesting_frame_1); 633 EXPECT_EQ(0U, infobar_service()->infobar_count()); 634 // Go back: navigate to a pending entry before requesting geolocation 635 // permission. 636 web_contents()->GetController().GoBack(); 637 // Request permission for the committed frame (not the pending one). 638 RequestGeolocationPermission(RequestID(0), requesting_frame_1); 639 // Ensure the infobar is created. 640 ASSERT_EQ(1U, infobar_service()->infobar_count()); 641 InfoBarDelegate* infobar_delegate = infobar_service()->infobar_at(0); 642 ASSERT_TRUE(infobar_delegate); 643 // Ensure the infobar wouldn't expire for a navigation to the committed entry. 644 content::LoadCommittedDetails details; 645 details.entry = web_contents()->GetController().GetLastCommittedEntry(); 646 EXPECT_FALSE(infobar_delegate->ShouldExpire(details)); 647 // Ensure the infobar will expire when we commit the pending navigation. 648 details.entry = web_contents()->GetController().GetActiveEntry(); 649 EXPECT_TRUE(infobar_delegate->ShouldExpire(details)); 650 651 // Delete the tab contents. 652 DeleteContents(); 653 delete infobar_delegate; 654 } 655