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 "base/compiler_specific.h" 6 #include "base/string_number_conversions.h" 7 #include "base/string_util.h" 8 #include "base/utf_string_conversions.h" 9 #include "chrome/browser/dom_operation_notification_details.h" 10 #include "chrome/browser/geolocation/geolocation_content_settings_map.h" 11 #include "chrome/browser/geolocation/geolocation_settings_state.h" 12 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h" 14 #include "chrome/browser/ui/browser.h" 15 #include "chrome/browser/ui/browser_list.h" 16 #include "chrome/common/chrome_paths.h" 17 #include "chrome/test/in_process_browser_test.h" 18 #include "chrome/test/ui_test_utils.h" 19 #include "content/browser/geolocation/arbitrator_dependency_factories_for_test.h" 20 #include "content/browser/geolocation/location_arbitrator.h" 21 #include "content/browser/geolocation/mock_location_provider.h" 22 #include "content/browser/renderer_host/render_view_host.h" 23 #include "content/browser/tab_contents/tab_contents.h" 24 #include "content/common/geoposition.h" 25 #include "content/common/notification_details.h" 26 #include "content/common/notification_service.h" 27 #include "content/common/notification_type.h" 28 #include "net/base/net_util.h" 29 #include "net/test/test_server.h" 30 31 namespace { 32 33 // Used to block until an iframe is loaded via a javascript call. 34 // Note: NavigateToURLBlockUntilNavigationsComplete doesn't seem to work for 35 // multiple embedded iframes, as notifications seem to be 'batched'. Instead, we 36 // load and wait one single frame here by calling a javascript function. 37 class IFrameLoader : public NotificationObserver { 38 public: 39 IFrameLoader(Browser* browser, int iframe_id, const GURL& url) 40 : navigation_completed_(false), 41 javascript_completed_(false) { 42 NavigationController* controller = 43 &browser->GetSelectedTabContents()->controller(); 44 registrar_.Add(this, NotificationType::LOAD_STOP, 45 Source<NavigationController>(controller)); 46 registrar_.Add(this, NotificationType::DOM_OPERATION_RESPONSE, 47 NotificationService::AllSources()); 48 std::string script = StringPrintf( 49 "window.domAutomationController.setAutomationId(0);" 50 "window.domAutomationController.send(addIFrame(%d, \"%s\"));", 51 iframe_id, 52 url.spec().c_str()); 53 browser->GetSelectedTabContents()->render_view_host()-> 54 ExecuteJavascriptInWebFrame(string16(), UTF8ToUTF16(script)); 55 ui_test_utils::RunMessageLoop(); 56 57 EXPECT_EQ(StringPrintf("\"%d\"", iframe_id), javascript_response_); 58 registrar_.RemoveAll(); 59 // Now that we loaded the iframe, let's fetch its src. 60 script = StringPrintf( 61 "window.domAutomationController.send(getIFrameSrc(%d))", iframe_id); 62 std::string iframe_src; 63 EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 64 browser->GetSelectedTabContents()->render_view_host(), 65 L"", UTF8ToWide(script), &iframe_src)); 66 iframe_url_ = GURL(iframe_src); 67 } 68 69 GURL iframe_url() const { return iframe_url_; } 70 71 virtual void Observe(NotificationType type, 72 const NotificationSource& source, 73 const NotificationDetails& details) { 74 if (type == NotificationType::LOAD_STOP) { 75 navigation_completed_ = true; 76 } else if (type == NotificationType::DOM_OPERATION_RESPONSE) { 77 Details<DomOperationNotificationDetails> dom_op_details(details); 78 javascript_response_ = dom_op_details->json(); 79 javascript_completed_ = true; 80 } 81 if (javascript_completed_ && navigation_completed_) 82 MessageLoopForUI::current()->Quit(); 83 } 84 85 private: 86 NotificationRegistrar registrar_; 87 88 // If true the navigation has completed. 89 bool navigation_completed_; 90 91 // If true the javascript call has completed. 92 bool javascript_completed_; 93 94 std::string javascript_response_; 95 96 // The URL for the iframe we just loaded. 97 GURL iframe_url_; 98 99 DISALLOW_COPY_AND_ASSIGN(IFrameLoader); 100 }; 101 102 class GeolocationNotificationObserver : public NotificationObserver { 103 public: 104 // If |wait_for_infobar| is true, AddWatchAndWaitForNotification will block 105 // until the infobar has been displayed; otherwise it will block until the 106 // navigation is completed. 107 explicit GeolocationNotificationObserver(bool wait_for_infobar) 108 : wait_for_infobar_(wait_for_infobar), 109 infobar_(NULL), 110 navigation_started_(false), 111 navigation_completed_(false) { 112 registrar_.Add(this, NotificationType::DOM_OPERATION_RESPONSE, 113 NotificationService::AllSources()); 114 if (wait_for_infobar) { 115 registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_ADDED, 116 NotificationService::AllSources()); 117 } else { 118 registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED, 119 NotificationService::AllSources()); 120 registrar_.Add(this, NotificationType::LOAD_START, 121 NotificationService::AllSources()); 122 registrar_.Add(this, NotificationType::LOAD_STOP, 123 NotificationService::AllSources()); 124 } 125 } 126 127 void AddWatchAndWaitForNotification(RenderViewHost* render_view_host, 128 const std::wstring& iframe_xpath) { 129 LOG(WARNING) << "will add geolocation watch"; 130 std::string script = 131 "window.domAutomationController.setAutomationId(0);" 132 "window.domAutomationController.send(geoStart());"; 133 render_view_host->ExecuteJavascriptInWebFrame(WideToUTF16Hack(iframe_xpath), 134 UTF8ToUTF16(script)); 135 ui_test_utils::RunMessageLoop(); 136 registrar_.RemoveAll(); 137 LOG(WARNING) << "got geolocation watch" << javascript_response_; 138 EXPECT_NE("\"0\"", javascript_response_); 139 if (wait_for_infobar_) { 140 EXPECT_TRUE(infobar_); 141 } else { 142 EXPECT_TRUE(navigation_completed_); 143 } 144 } 145 146 // NotificationObserver 147 virtual void Observe(NotificationType type, 148 const NotificationSource& source, 149 const NotificationDetails& details) { 150 if (type.value == NotificationType::TAB_CONTENTS_INFOBAR_ADDED) { 151 infobar_ = Details<InfoBarDelegate>(details).ptr(); 152 ASSERT_TRUE(infobar_->GetIcon()); 153 ASSERT_TRUE(infobar_->AsConfirmInfoBarDelegate()); 154 } else if (type == NotificationType::DOM_OPERATION_RESPONSE) { 155 Details<DomOperationNotificationDetails> dom_op_details(details); 156 javascript_response_ = dom_op_details->json(); 157 LOG(WARNING) << "javascript_response " << javascript_response_; 158 } else if (type == NotificationType::NAV_ENTRY_COMMITTED || 159 type == NotificationType::LOAD_START) { 160 navigation_started_ = true; 161 } else if (type == NotificationType::LOAD_STOP) { 162 if (navigation_started_) { 163 navigation_started_ = false; 164 navigation_completed_ = true; 165 } 166 } 167 168 // We're either waiting for just the inforbar, or for both a javascript 169 // prompt and response. 170 if (wait_for_infobar_ && infobar_) 171 MessageLoopForUI::current()->Quit(); 172 else if (navigation_completed_ && !javascript_response_.empty()) 173 MessageLoopForUI::current()->Quit(); 174 } 175 176 NotificationRegistrar registrar_; 177 bool wait_for_infobar_; 178 InfoBarDelegate* infobar_; 179 bool navigation_started_; 180 bool navigation_completed_; 181 std::string javascript_response_; 182 }; 183 184 void NotifyGeoposition(const Geoposition& geoposition) { 185 DCHECK(MockLocationProvider::instance_); 186 MockLocationProvider::instance_->HandlePositionChanged(geoposition); 187 LOG(WARNING) << "MockLocationProvider listeners updated"; 188 } 189 190 // This is a browser test for Geolocation. 191 // It exercises various integration points from javascript <-> browser: 192 // 1. Infobar is displayed when a geolocation is requested from an unauthorized 193 // origin. 194 // 2. Denying the infobar triggers the correct error callback. 195 // 3. Allowing the infobar does not trigger an error, and allow a geoposition to 196 // be passed to javascript. 197 // 4. Permissions persisted in disk are respected. 198 // 5. Incognito profiles don't use saved permissions. 199 class GeolocationBrowserTest : public InProcessBrowserTest { 200 public: 201 GeolocationBrowserTest() 202 : infobar_(NULL), 203 current_browser_(NULL), 204 html_for_tests_("files/geolocation/simple.html"), 205 started_test_server_(false), 206 dependency_factory_( 207 new GeolocationArbitratorDependencyFactoryWithLocationProvider( 208 &NewAutoSuccessMockNetworkLocationProvider)) { 209 EnableDOMAutomation(); 210 } 211 212 // InProcessBrowserTest 213 virtual void SetUpInProcessBrowserTestFixture() { 214 GeolocationArbitrator::SetDependencyFactoryForTest( 215 dependency_factory_.get()); 216 } 217 218 // InProcessBrowserTest 219 virtual void TearDownInProcessBrowserTestFixture() { 220 LOG(WARNING) << "TearDownInProcessBrowserTestFixture. Test Finished."; 221 GeolocationArbitrator::SetDependencyFactoryForTest(NULL); 222 } 223 224 enum InitializationOptions { 225 INITIALIZATION_NONE, 226 INITIALIZATION_OFFTHERECORD, 227 INITIALIZATION_NEWTAB, 228 INITIALIZATION_IFRAMES, 229 }; 230 231 bool Initialize(InitializationOptions options) WARN_UNUSED_RESULT { 232 if (!started_test_server_) 233 started_test_server_ = test_server()->Start(); 234 EXPECT_TRUE(started_test_server_); 235 if (!started_test_server_) 236 return false; 237 238 current_url_ = test_server()->GetURL(html_for_tests_); 239 LOG(WARNING) << "before navigate"; 240 if (options == INITIALIZATION_OFFTHERECORD) { 241 ui_test_utils::OpenURLOffTheRecord(browser()->profile(), current_url_); 242 current_browser_ = BrowserList::FindBrowserWithType( 243 browser()->profile()->GetOffTheRecordProfile(), Browser::TYPE_NORMAL, 244 false); 245 } else if (options == INITIALIZATION_NEWTAB) { 246 current_browser_ = browser(); 247 current_browser_->NewTab(); 248 ui_test_utils::NavigateToURL(current_browser_, current_url_); 249 } else if (options == INITIALIZATION_IFRAMES) { 250 current_browser_ = browser(); 251 ui_test_utils::NavigateToURL(current_browser_, current_url_); 252 } else { 253 current_browser_ = browser(); 254 ui_test_utils::NavigateToURL(current_browser_, current_url_); 255 } 256 LOG(WARNING) << "after navigate"; 257 258 EXPECT_TRUE(current_browser_); 259 if (!current_browser_) 260 return false; 261 262 return true; 263 } 264 265 void LoadIFrames(int number_iframes) { 266 // Limit to 3 iframes. 267 DCHECK(0 < number_iframes && number_iframes <= 3); 268 iframe_urls_.resize(number_iframes); 269 for (int i = 0; i < number_iframes; ++i) { 270 IFrameLoader loader(current_browser_, i, GURL()); 271 iframe_urls_[i] = loader.iframe_url(); 272 } 273 } 274 275 void AddGeolocationWatch(bool wait_for_infobar) { 276 GeolocationNotificationObserver notification_observer(wait_for_infobar); 277 notification_observer.AddWatchAndWaitForNotification( 278 current_browser_->GetSelectedTabContents()->render_view_host(), 279 iframe_xpath_); 280 if (wait_for_infobar) { 281 EXPECT_TRUE(notification_observer.infobar_); 282 infobar_ = notification_observer.infobar_; 283 } 284 } 285 286 Geoposition GeopositionFromLatLong(double latitude, double longitude) { 287 Geoposition geoposition; 288 geoposition.latitude = latitude; 289 geoposition.longitude = longitude; 290 geoposition.accuracy = 0; 291 geoposition.error_code = Geoposition::ERROR_CODE_NONE; 292 // Webkit compares the timestamp to wall clock time, so we need 293 // it to be contemporary. 294 geoposition.timestamp = base::Time::Now(); 295 EXPECT_TRUE(geoposition.IsValidFix()); 296 return geoposition; 297 } 298 299 void CheckGeoposition(const Geoposition& geoposition) { 300 // Checks we have no error. 301 CheckStringValueFromJavascript("0", "geoGetLastError()"); 302 CheckStringValueFromJavascript(base::DoubleToString(geoposition.latitude), 303 "geoGetLastPositionLatitude()"); 304 CheckStringValueFromJavascript(base::DoubleToString(geoposition.longitude), 305 "geoGetLastPositionLongitude()"); 306 } 307 308 void SetInfobarResponse(const GURL& requesting_url, bool allowed) { 309 TabContents* tab_contents = current_browser_->GetSelectedTabContents(); 310 TabSpecificContentSettings* content_settings = 311 tab_contents->GetTabSpecificContentSettings(); 312 const GeolocationSettingsState& settings_state = 313 content_settings->geolocation_settings_state(); 314 size_t state_map_size = settings_state.state_map().size(); 315 ASSERT_TRUE(infobar_); 316 LOG(WARNING) << "will set infobar response"; 317 if (allowed) 318 infobar_->AsConfirmInfoBarDelegate()->Accept(); 319 else 320 infobar_->AsConfirmInfoBarDelegate()->Cancel(); 321 WaitForNavigation(); 322 tab_contents->RemoveInfoBar(infobar_); 323 LOG(WARNING) << "infobar response set"; 324 infobar_ = NULL; 325 EXPECT_GT(settings_state.state_map().size(), state_map_size); 326 GURL requesting_origin = requesting_url.GetOrigin(); 327 EXPECT_EQ(1U, settings_state.state_map().count(requesting_origin)); 328 ContentSetting expected_setting = 329 allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; 330 EXPECT_EQ(expected_setting, 331 settings_state.state_map().find(requesting_origin)->second); 332 } 333 334 void WaitForNavigation() { 335 LOG(WARNING) << "will block for navigation"; 336 NavigationController* controller = 337 ¤t_browser_->GetSelectedTabContents()->controller(); 338 ui_test_utils::WaitForNavigation(controller); 339 LOG(WARNING) << "navigated"; 340 } 341 342 void CheckStringValueFromJavascriptForTab( 343 const std::string& expected, const std::string& function, 344 TabContents* tab_contents) { 345 std::string script = StringPrintf( 346 "window.domAutomationController.send(%s)", function.c_str()); 347 std::string result; 348 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 349 tab_contents->render_view_host(), 350 iframe_xpath_, UTF8ToWide(script), &result)); 351 EXPECT_EQ(expected, result); 352 } 353 354 void CheckStringValueFromJavascript( 355 const std::string& expected, const std::string& function) { 356 CheckStringValueFromJavascriptForTab( 357 expected, function, current_browser_->GetSelectedTabContents()); 358 } 359 360 InfoBarDelegate* infobar_; 361 Browser* current_browser_; 362 // path element of a URL referencing the html content for this test. 363 std::string html_for_tests_; 364 // This member defines the iframe (or top-level page, if empty) where the 365 // javascript calls will run. 366 std::wstring iframe_xpath_; 367 // The current url for the top level page. 368 GURL current_url_; 369 // If not empty, the GURLs for the iframes loaded by LoadIFrames(). 370 std::vector<GURL> iframe_urls_; 371 372 // TODO(phajdan.jr): Remove after we can ask TestServer whether it is started. 373 bool started_test_server_; 374 375 scoped_refptr<GeolocationArbitratorDependencyFactory> dependency_factory_; 376 }; 377 378 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DisplaysPermissionBar) { 379 ASSERT_TRUE(Initialize(INITIALIZATION_NONE)); 380 AddGeolocationWatch(true); 381 } 382 383 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, Geoposition) { 384 ASSERT_TRUE(Initialize(INITIALIZATION_NONE)); 385 AddGeolocationWatch(true); 386 SetInfobarResponse(current_url_, true); 387 CheckGeoposition(MockLocationProvider::instance_->position_); 388 } 389 390 // Crashy, http://crbug.com/70585. 391 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, 392 DISABLED_ErrorOnPermissionDenied) { 393 ASSERT_TRUE(Initialize(INITIALIZATION_NONE)); 394 AddGeolocationWatch(true); 395 // Infobar was displayed, deny access and check for error code. 396 SetInfobarResponse(current_url_, false); 397 CheckStringValueFromJavascript("1", "geoGetLastError()"); 398 } 399 400 // http://crbug.com/44589. Hangs on Mac, crashes on Windows 401 #if defined(OS_MACOSX) || defined(OS_WINDOWS) 402 #define MAYBE_NoInfobarForSecondTab DISABLED_NoInfobarForSecondTab 403 #else 404 #define MAYBE_NoInfobarForSecondTab NoInfobarForSecondTab 405 #endif 406 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, MAYBE_NoInfobarForSecondTab) { 407 ASSERT_TRUE(Initialize(INITIALIZATION_NONE)); 408 AddGeolocationWatch(true); 409 SetInfobarResponse(current_url_, true); 410 // Disables further prompts from this tab. 411 CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)"); 412 413 // Checks infobar will not be created a second tab. 414 ASSERT_TRUE(Initialize(INITIALIZATION_NEWTAB)); 415 AddGeolocationWatch(false); 416 CheckGeoposition(MockLocationProvider::instance_->position_); 417 } 418 419 // http://crbug.com/44589. Hangs on Mac, crashes on Windows 420 #if defined(OS_MACOSX) || defined(OS_WINDOWS) 421 #define MAYBE_NoInfobarForDeniedOrigin DISABLED_NoInfobarForDeniedOrigin 422 #else 423 #define MAYBE_NoInfobarForDeniedOrigin NoInfobarForDeniedOrigin 424 #endif 425 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, MAYBE_NoInfobarForDeniedOrigin) { 426 ASSERT_TRUE(Initialize(INITIALIZATION_NONE)); 427 current_browser_->profile()->GetGeolocationContentSettingsMap()-> 428 SetContentSetting(current_url_, current_url_, CONTENT_SETTING_BLOCK); 429 AddGeolocationWatch(false); 430 // Checks we have an error for this denied origin. 431 CheckStringValueFromJavascript("1", "geoGetLastError()"); 432 // Checks infobar will not be created a second tab. 433 ASSERT_TRUE(Initialize(INITIALIZATION_NEWTAB)); 434 AddGeolocationWatch(false); 435 CheckStringValueFromJavascript("1", "geoGetLastError()"); 436 } 437 438 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfobarForAllowedOrigin) { 439 ASSERT_TRUE(Initialize(INITIALIZATION_NONE)); 440 current_browser_->profile()->GetGeolocationContentSettingsMap()-> 441 SetContentSetting(current_url_, current_url_, CONTENT_SETTING_ALLOW); 442 // Checks no infobar will be created and there's no error callback. 443 AddGeolocationWatch(false); 444 CheckGeoposition(MockLocationProvider::instance_->position_); 445 } 446 447 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfobarForOffTheRecord) { 448 // First, check infobar will be created for regular profile 449 ASSERT_TRUE(Initialize(INITIALIZATION_NONE)); 450 AddGeolocationWatch(true); 451 // Response will be persisted 452 SetInfobarResponse(current_url_, true); 453 CheckGeoposition(MockLocationProvider::instance_->position_); 454 // Disables further prompts from this tab. 455 CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)"); 456 // Go incognito, and checks no infobar will be created. 457 ASSERT_TRUE(Initialize(INITIALIZATION_OFFTHERECORD)); 458 AddGeolocationWatch(false); 459 CheckGeoposition(MockLocationProvider::instance_->position_); 460 } 461 462 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, IFramesWithFreshPosition) { 463 html_for_tests_ = "files/geolocation/iframes_different_origin.html"; 464 ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES)); 465 LoadIFrames(2); 466 LOG(WARNING) << "frames loaded"; 467 468 iframe_xpath_ = L"//iframe[@id='iframe_0']"; 469 AddGeolocationWatch(true); 470 SetInfobarResponse(iframe_urls_[0], true); 471 CheckGeoposition(MockLocationProvider::instance_->position_); 472 // Disables further prompts from this iframe. 473 CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)"); 474 475 // Test second iframe from a different origin with a cached geoposition will 476 // create the infobar. 477 iframe_xpath_ = L"//iframe[@id='iframe_1']"; 478 AddGeolocationWatch(true); 479 480 // Back to the first frame, enable navigation and refresh geoposition. 481 iframe_xpath_ = L"//iframe[@id='iframe_0']"; 482 CheckStringValueFromJavascript("1", "geoSetMaxNavigateCount(1)"); 483 // MockLocationProvider must have been created. 484 ASSERT_TRUE(MockLocationProvider::instance_); 485 Geoposition fresh_position = GeopositionFromLatLong(3.17, 4.23); 486 NotifyGeoposition(fresh_position); 487 WaitForNavigation(); 488 CheckGeoposition(fresh_position); 489 490 // Disable navigation for this frame. 491 CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)"); 492 493 // Now go ahead an authorize the second frame. 494 iframe_xpath_ = L"//iframe[@id='iframe_1']"; 495 // Infobar was displayed, allow access and check there's no error code. 496 SetInfobarResponse(iframe_urls_[1], true); 497 LOG(WARNING) << "Checking position..."; 498 CheckGeoposition(fresh_position); 499 LOG(WARNING) << "...done."; 500 } 501 502 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, IFramesWithCachedPosition) { 503 html_for_tests_ = "files/geolocation/iframes_different_origin.html"; 504 ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES)); 505 LoadIFrames(2); 506 507 iframe_xpath_ = L"//iframe[@id='iframe_0']"; 508 AddGeolocationWatch(true); 509 SetInfobarResponse(iframe_urls_[0], true); 510 CheckGeoposition(MockLocationProvider::instance_->position_); 511 512 // Refresh geoposition, but let's not yet create the watch on the second frame 513 // so that it'll fetch from cache. 514 // MockLocationProvider must have been created. 515 ASSERT_TRUE(MockLocationProvider::instance_); 516 Geoposition cached_position = GeopositionFromLatLong(5.67, 8.09); 517 NotifyGeoposition(cached_position); 518 WaitForNavigation(); 519 CheckGeoposition(cached_position); 520 521 // Disable navigation for this frame. 522 CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)"); 523 524 // Now go ahead an authorize the second frame. 525 iframe_xpath_ = L"//iframe[@id='iframe_1']"; 526 AddGeolocationWatch(true); 527 // WebKit will use its cache, but we also broadcast a position shortly 528 // afterwards. We're only interested in the first navigation for the success 529 // callback from the cached position. 530 CheckStringValueFromJavascript("1", "geoSetMaxNavigateCount(1)"); 531 SetInfobarResponse(iframe_urls_[1], true); 532 CheckGeoposition(cached_position); 533 } 534 535 // See http://crbug.com/56033 536 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, 537 DISABLED_CancelPermissionForFrame) { 538 html_for_tests_ = "files/geolocation/iframes_different_origin.html"; 539 ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES)); 540 LoadIFrames(2); 541 LOG(WARNING) << "frames loaded"; 542 543 iframe_xpath_ = L"//iframe[@id='iframe_0']"; 544 AddGeolocationWatch(true); 545 SetInfobarResponse(iframe_urls_[0], true); 546 CheckGeoposition(MockLocationProvider::instance_->position_); 547 // Disables further prompts from this iframe. 548 CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)"); 549 550 // Test second iframe from a different origin with a cached geoposition will 551 // create the infobar. 552 iframe_xpath_ = L"//iframe[@id='iframe_1']"; 553 AddGeolocationWatch(true); 554 555 size_t num_infobars_before_cancel = 556 current_browser_->GetSelectedTabContents()->infobar_count(); 557 // Change the iframe, and ensure the infobar is gone. 558 IFrameLoader change_iframe_1(current_browser_, 1, current_url_); 559 size_t num_infobars_after_cancel = 560 current_browser_->GetSelectedTabContents()->infobar_count(); 561 EXPECT_EQ(num_infobars_before_cancel, num_infobars_after_cancel + 1); 562 } 563 564 // Disabled, http://crbug.com/66959. 565 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DISABLED_InvalidUrlRequest) { 566 // Tests that an invalid URL (e.g. from a popup window) is rejected 567 // correctly. Also acts as a regression test for http://crbug.com/40478 568 html_for_tests_ = "files/geolocation/invalid_request_url.html"; 569 ASSERT_TRUE(Initialize(INITIALIZATION_NONE)); 570 TabContents* original_tab = current_browser_->GetSelectedTabContents(); 571 CheckStringValueFromJavascript("1", "requestGeolocationFromInvalidUrl()"); 572 CheckStringValueFromJavascriptForTab("1", "isAlive()", original_tab); 573 } 574 575 // Crashy, http://crbug.com/66400. 576 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DISABLED_NoInfoBarBeforeStart) { 577 // See http://crbug.com/42789 578 html_for_tests_ = "files/geolocation/iframes_different_origin.html"; 579 ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES)); 580 LoadIFrames(2); 581 LOG(WARNING) << "frames loaded"; 582 583 // Access navigator.geolocation, but ensure it won't request permission. 584 iframe_xpath_ = L"//iframe[@id='iframe_1']"; 585 CheckStringValueFromJavascript("object", "geoAccessNavigatorGeolocation()"); 586 587 iframe_xpath_ = L"//iframe[@id='iframe_0']"; 588 AddGeolocationWatch(true); 589 SetInfobarResponse(iframe_urls_[0], true); 590 CheckGeoposition(MockLocationProvider::instance_->position_); 591 CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)"); 592 593 // Permission should be requested after adding a watch. 594 iframe_xpath_ = L"//iframe[@id='iframe_1']"; 595 AddGeolocationWatch(true); 596 SetInfobarResponse(iframe_urls_[1], true); 597 CheckGeoposition(MockLocationProvider::instance_->position_); 598 } 599 600 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, TwoWatchesInOneFrame) { 601 html_for_tests_ = "files/geolocation/two_watches.html"; 602 ASSERT_TRUE(Initialize(INITIALIZATION_NONE)); 603 // First, set the JavaScript to navigate when it receives |final_position|. 604 const Geoposition final_position = GeopositionFromLatLong(3.17, 4.23); 605 std::string script = StringPrintf( 606 "window.domAutomationController.send(geoSetFinalPosition(%f, %f))", 607 final_position.latitude, final_position.longitude); 608 std::string js_result; 609 EXPECT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 610 current_browser_->GetSelectedTabContents()->render_view_host(), 611 L"", UTF8ToWide(script), &js_result)); 612 EXPECT_EQ(js_result, "ok"); 613 614 // Send a position which both geolocation watches will receive. 615 AddGeolocationWatch(true); 616 SetInfobarResponse(current_url_, true); 617 CheckGeoposition(MockLocationProvider::instance_->position_); 618 619 // The second watch will now have cancelled. Ensure an update still makes 620 // its way through to the first watcher. 621 NotifyGeoposition(final_position); 622 WaitForNavigation(); 623 CheckGeoposition(final_position); 624 } 625 626 // Hangs flakily, http://crbug.com/70588. 627 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DISABLED_TabDestroyed) { 628 html_for_tests_ = "files/geolocation/tab_destroyed.html"; 629 ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES)); 630 LoadIFrames(3); 631 632 iframe_xpath_ = L"//iframe[@id='iframe_0']"; 633 AddGeolocationWatch(true); 634 635 iframe_xpath_ = L"//iframe[@id='iframe_1']"; 636 AddGeolocationWatch(false); 637 638 iframe_xpath_ = L"//iframe[@id='iframe_2']"; 639 AddGeolocationWatch(false); 640 641 std::string script = 642 "window.domAutomationController.setAutomationId(0);" 643 "window.domAutomationController.send(window.close());"; 644 bool result = 645 ui_test_utils::ExecuteJavaScript( 646 current_browser_->GetSelectedTabContents()->render_view_host(), 647 L"", UTF8ToWide(script)); 648 EXPECT_EQ(result, true); 649 } 650 651 } // namespace 652