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