Home | History | Annotate | Download | only in geolocation
      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         &current_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