Home | History | Annotate | Download | only in geolocation
      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 <string>
      6 
      7 #include "base/compiler_specific.h"
      8 #include "base/strings/string_number_conversions.h"
      9 #include "base/strings/stringprintf.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "chrome/browser/chrome_notification_types.h"
     12 #include "chrome/browser/content_settings/content_settings_usages_state.h"
     13 #include "chrome/browser/content_settings/host_content_settings_map.h"
     14 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
     15 #include "chrome/browser/infobars/confirm_infobar_delegate.h"
     16 #include "chrome/browser/infobars/infobar.h"
     17 #include "chrome/browser/infobars/infobar_service.h"
     18 #include "chrome/browser/profiles/profile.h"
     19 #include "chrome/browser/ui/browser.h"
     20 #include "chrome/browser/ui/browser_commands.h"
     21 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     22 #include "chrome/common/chrome_paths.h"
     23 #include "chrome/common/content_settings_pattern.h"
     24 #include "chrome/test/base/in_process_browser_test.h"
     25 #include "chrome/test/base/ui_test_utils.h"
     26 #include "content/public/browser/dom_operation_notification_details.h"
     27 #include "content/public/browser/navigation_controller.h"
     28 #include "content/public/browser/notification_details.h"
     29 #include "content/public/browser/notification_service.h"
     30 #include "content/public/browser/render_view_host.h"
     31 #include "content/public/browser/web_contents.h"
     32 #include "content/public/test/browser_test_utils.h"
     33 #include "net/base/net_util.h"
     34 #include "net/test/embedded_test_server/embedded_test_server.h"
     35 
     36 using content::DomOperationNotificationDetails;
     37 using content::NavigationController;
     38 using content::WebContents;
     39 
     40 namespace {
     41 
     42 
     43 // IFrameLoader ---------------------------------------------------------------
     44 
     45 // Used to block until an iframe is loaded via a javascript call.
     46 // Note: NavigateToURLBlockUntilNavigationsComplete doesn't seem to work for
     47 // multiple embedded iframes, as notifications seem to be 'batched'. Instead, we
     48 // load and wait one single frame here by calling a javascript function.
     49 class IFrameLoader : public content::NotificationObserver {
     50  public:
     51   IFrameLoader(Browser* browser, int iframe_id, const GURL& url);
     52   virtual ~IFrameLoader();
     53 
     54   // content::NotificationObserver:
     55   virtual void Observe(int type,
     56                        const content::NotificationSource& source,
     57                        const content::NotificationDetails& details) OVERRIDE;
     58 
     59   const GURL& iframe_url() const { return iframe_url_; }
     60 
     61  private:
     62   content::NotificationRegistrar registrar_;
     63 
     64   // If true the navigation has completed.
     65   bool navigation_completed_;
     66 
     67   // If true the javascript call has completed.
     68   bool javascript_completed_;
     69 
     70   std::string javascript_response_;
     71 
     72   // The URL for the iframe we just loaded.
     73   GURL iframe_url_;
     74 
     75   DISALLOW_COPY_AND_ASSIGN(IFrameLoader);
     76 };
     77 
     78 IFrameLoader::IFrameLoader(Browser* browser, int iframe_id, const GURL& url)
     79     : navigation_completed_(false),
     80       javascript_completed_(false) {
     81   WebContents* web_contents =
     82       browser->tab_strip_model()->GetActiveWebContents();
     83   NavigationController* controller = &web_contents->GetController();
     84   registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
     85                  content::Source<NavigationController>(controller));
     86   registrar_.Add(this, content::NOTIFICATION_DOM_OPERATION_RESPONSE,
     87                  content::NotificationService::AllSources());
     88   std::string script(base::StringPrintf(
     89       "window.domAutomationController.setAutomationId(0);"
     90       "window.domAutomationController.send(addIFrame(%d, \"%s\"));",
     91       iframe_id, url.spec().c_str()));
     92   web_contents->GetRenderViewHost()->ExecuteJavascriptInWebFrame(
     93       base::string16(), UTF8ToUTF16(script));
     94   content::RunMessageLoop();
     95 
     96   EXPECT_EQ(base::StringPrintf("\"%d\"", iframe_id), javascript_response_);
     97   registrar_.RemoveAll();
     98   // Now that we loaded the iframe, let's fetch its src.
     99   script = base::StringPrintf(
    100       "window.domAutomationController.send(getIFrameSrc(%d))", iframe_id);
    101   std::string iframe_src;
    102   EXPECT_TRUE(content::ExecuteScriptAndExtractString(web_contents, script,
    103                                                      &iframe_src));
    104   iframe_url_ = GURL(iframe_src);
    105 }
    106 
    107 IFrameLoader::~IFrameLoader() {
    108 }
    109 
    110 void IFrameLoader::Observe(int type,
    111                            const content::NotificationSource& source,
    112                            const content::NotificationDetails& details) {
    113   if (type == content::NOTIFICATION_LOAD_STOP) {
    114     navigation_completed_ = true;
    115   } else if (type == content::NOTIFICATION_DOM_OPERATION_RESPONSE) {
    116     content::Details<DomOperationNotificationDetails> dom_op_details(details);
    117     javascript_response_ = dom_op_details->json;
    118     javascript_completed_ = true;
    119   }
    120   if (javascript_completed_ && navigation_completed_)
    121     base::MessageLoopForUI::current()->Quit();
    122 }
    123 
    124 
    125 // GeolocationNotificationObserver --------------------------------------------
    126 
    127 class GeolocationNotificationObserver : public content::NotificationObserver {
    128  public:
    129   // If |wait_for_infobar| is true, AddWatchAndWaitForNotification will block
    130   // until the infobar has been displayed; otherwise it will block until the
    131   // navigation is completed.
    132   explicit GeolocationNotificationObserver(bool wait_for_infobar);
    133   virtual ~GeolocationNotificationObserver();
    134 
    135   // content::NotificationObserver:
    136   virtual void Observe(int type,
    137                        const content::NotificationSource& source,
    138                        const content::NotificationDetails& details) OVERRIDE;
    139 
    140   void AddWatchAndWaitForNotification(content::RenderViewHost* render_view_host,
    141                                       const std::string& iframe_xpath);
    142 
    143   bool has_infobar() const { return !!infobar_; }
    144   InfoBar* infobar() { return infobar_; }
    145 
    146  private:
    147   content::NotificationRegistrar registrar_;
    148   bool wait_for_infobar_;
    149   InfoBar* infobar_;
    150   bool navigation_started_;
    151   bool navigation_completed_;
    152   std::string javascript_response_;
    153 
    154   DISALLOW_COPY_AND_ASSIGN(GeolocationNotificationObserver);
    155 };
    156 
    157 GeolocationNotificationObserver::GeolocationNotificationObserver(
    158     bool wait_for_infobar)
    159     : wait_for_infobar_(wait_for_infobar),
    160       infobar_(NULL),
    161       navigation_started_(false),
    162       navigation_completed_(false) {
    163   registrar_.Add(this, content::NOTIFICATION_DOM_OPERATION_RESPONSE,
    164                  content::NotificationService::AllSources());
    165   if (wait_for_infobar) {
    166     registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
    167                    content::NotificationService::AllSources());
    168   } else {
    169     registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
    170                    content::NotificationService::AllSources());
    171     registrar_.Add(this, content::NOTIFICATION_LOAD_START,
    172                    content::NotificationService::AllSources());
    173     registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
    174                    content::NotificationService::AllSources());
    175   }
    176 }
    177 
    178 GeolocationNotificationObserver::~GeolocationNotificationObserver() {
    179 }
    180 
    181 void GeolocationNotificationObserver::Observe(
    182     int type,
    183     const content::NotificationSource& source,
    184     const content::NotificationDetails& details) {
    185   if (type == chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED) {
    186     infobar_ = content::Details<InfoBar::AddedDetails>(details).ptr();
    187     ASSERT_FALSE(infobar_->delegate()->GetIcon().IsEmpty());
    188     ASSERT_TRUE(infobar_->delegate()->AsConfirmInfoBarDelegate());
    189   } else if (type == content::NOTIFICATION_DOM_OPERATION_RESPONSE) {
    190     content::Details<DomOperationNotificationDetails> dom_op_details(details);
    191     javascript_response_ = dom_op_details->json;
    192     LOG(WARNING) << "javascript_response " << javascript_response_;
    193   } else if ((type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) ||
    194              (type == content::NOTIFICATION_LOAD_START)) {
    195     navigation_started_ = true;
    196   } else if ((type == content::NOTIFICATION_LOAD_STOP) && navigation_started_) {
    197     navigation_started_ = false;
    198     navigation_completed_ = true;
    199   }
    200 
    201   // We're either waiting for just the infobar, or for both a javascript
    202   // prompt and response.
    203   if ((wait_for_infobar_ && infobar_) ||
    204       (navigation_completed_ && !javascript_response_.empty()))
    205     base::MessageLoopForUI::current()->Quit();
    206 }
    207 
    208 void GeolocationNotificationObserver::AddWatchAndWaitForNotification(
    209     content::RenderViewHost* render_view_host,
    210     const std::string& iframe_xpath) {
    211   LOG(WARNING) << "will add geolocation watch";
    212   std::string script(
    213       "window.domAutomationController.setAutomationId(0);"
    214       "window.domAutomationController.send(geoStart());");
    215   render_view_host->ExecuteJavascriptInWebFrame(UTF8ToUTF16(iframe_xpath),
    216                                                 UTF8ToUTF16(script));
    217   content::RunMessageLoop();
    218   registrar_.RemoveAll();
    219   LOG(WARNING) << "got geolocation watch" << javascript_response_;
    220   EXPECT_NE("\"0\"", javascript_response_);
    221   EXPECT_TRUE(wait_for_infobar_ ? (infobar_ != NULL) : navigation_completed_);
    222 }
    223 
    224 }  // namespace
    225 
    226 
    227 // GeolocationBrowserTest -----------------------------------------------------
    228 
    229 // This is a browser test for Geolocation.
    230 // It exercises various integration points from javascript <-> browser:
    231 // 1. Infobar is displayed when a geolocation is requested from an unauthorized
    232 // origin.
    233 // 2. Denying the infobar triggers the correct error callback.
    234 // 3. Allowing the infobar does not trigger an error, and allow a geoposition to
    235 // be passed to javascript.
    236 // 4. Permissions persisted in disk are respected.
    237 // 5. Incognito profiles don't use saved permissions.
    238 class GeolocationBrowserTest : public InProcessBrowserTest {
    239  public:
    240   enum InitializationOptions {
    241     INITIALIZATION_NONE,
    242     INITIALIZATION_OFFTHERECORD,
    243     INITIALIZATION_NEWTAB,
    244     INITIALIZATION_IFRAMES,
    245   };
    246 
    247   GeolocationBrowserTest();
    248   virtual ~GeolocationBrowserTest();
    249 
    250   // InProcessBrowserTest:
    251   virtual void SetUpOnMainThread() OVERRIDE;
    252   virtual void TearDownInProcessBrowserTestFixture() OVERRIDE;
    253 
    254   Browser* current_browser() { return current_browser_; }
    255   void set_html_for_tests(const std::string& html_for_tests) {
    256     html_for_tests_ = html_for_tests;
    257   }
    258   const std::string& iframe_xpath() const { return iframe_xpath_; }
    259   void set_iframe_xpath(const std::string& iframe_xpath) {
    260     iframe_xpath_ = iframe_xpath;
    261   }
    262   const GURL& current_url() const { return current_url_; }
    263   const GURL& iframe_url(size_t i) const { return iframe_urls_[i]; }
    264   double fake_latitude() const { return fake_latitude_; }
    265   double fake_longitude() const { return fake_longitude_; }
    266 
    267   // Initializes the test server and navigates to the initial url.
    268   bool Initialize(InitializationOptions options) WARN_UNUSED_RESULT;
    269 
    270   // Loads the specified number of iframes.
    271   void LoadIFrames(int number_iframes);
    272 
    273   // Start watching for geolocation notifications. If |wait_for_infobar| is
    274   // true, wait for the infobar to be displayed. Otherwise wait for a javascript
    275   // response.
    276   void AddGeolocationWatch(bool wait_for_infobar);
    277 
    278   // Checks that no errors have been received in javascript, and checks that the
    279   // position most recently received in javascript matches |latitude| and
    280   // |longitude|.
    281   void CheckGeoposition(double latitude, double longitude);
    282 
    283   // For |requesting_url| if |allowed| is true accept the infobar. Otherwise
    284   // cancel it.
    285   void SetInfoBarResponse(const GURL& requesting_url, bool allowed);
    286 
    287   // Executes |function| in |web_contents| and checks that the return value
    288   // matches |expected|.
    289   void CheckStringValueFromJavascriptForTab(const std::string& expected,
    290                                             const std::string& function,
    291                                             WebContents* web_contents);
    292 
    293   // Executes |function| and checks that the return value matches |expected|.
    294   void CheckStringValueFromJavascript(const std::string& expected,
    295                                       const std::string& function);
    296 
    297   // Sets a new position and sends a notification with the new position.
    298   void NotifyGeoposition(double latitude, double longitude);
    299 
    300  private:
    301   InfoBar* infobar_;
    302   Browser* current_browser_;
    303   // path element of a URL referencing the html content for this test.
    304   std::string html_for_tests_;
    305   // This member defines the iframe (or top-level page, if empty) where the
    306   // javascript calls will run.
    307   std::string iframe_xpath_;
    308   // The current url for the top level page.
    309   GURL current_url_;
    310   // If not empty, the GURLs for the iframes loaded by LoadIFrames().
    311   std::vector<GURL> iframe_urls_;
    312   double fake_latitude_;
    313   double fake_longitude_;
    314 
    315   DISALLOW_COPY_AND_ASSIGN(GeolocationBrowserTest);
    316 };
    317 
    318 GeolocationBrowserTest::GeolocationBrowserTest()
    319   : infobar_(NULL),
    320     current_browser_(NULL),
    321     html_for_tests_("/geolocation/simple.html"),
    322     fake_latitude_(1.23),
    323     fake_longitude_(4.56) {
    324 }
    325 
    326 GeolocationBrowserTest::~GeolocationBrowserTest() {
    327 }
    328 
    329 void GeolocationBrowserTest::SetUpOnMainThread() {
    330   ui_test_utils::OverrideGeolocation(fake_latitude_, fake_longitude_);
    331 }
    332 
    333 void GeolocationBrowserTest::TearDownInProcessBrowserTestFixture() {
    334   LOG(WARNING) << "TearDownInProcessBrowserTestFixture. Test Finished.";
    335 }
    336 
    337 bool GeolocationBrowserTest::Initialize(InitializationOptions options) {
    338   if (!embedded_test_server()->Started() &&
    339       !embedded_test_server()->InitializeAndWaitUntilReady()) {
    340     ADD_FAILURE() << "Test server failed to start.";
    341     return false;
    342   }
    343 
    344   current_url_ = embedded_test_server()->GetURL(html_for_tests_);
    345   LOG(WARNING) << "before navigate";
    346   if (options == INITIALIZATION_OFFTHERECORD) {
    347     current_browser_ = ui_test_utils::OpenURLOffTheRecord(
    348         browser()->profile(), current_url_);
    349   } else {
    350     current_browser_ = browser();
    351     if (options == INITIALIZATION_NEWTAB)
    352       chrome::NewTab(current_browser_);
    353     ui_test_utils::NavigateToURL(current_browser_, current_url_);
    354   }
    355   LOG(WARNING) << "after navigate";
    356 
    357   EXPECT_TRUE(current_browser_);
    358   return !!current_browser_;
    359 }
    360 
    361 void GeolocationBrowserTest::LoadIFrames(int number_iframes) {
    362   // Limit to 3 iframes.
    363   DCHECK_LT(0, number_iframes);
    364   DCHECK_LE(number_iframes, 3);
    365   iframe_urls_.resize(number_iframes);
    366   for (int i = 0; i < number_iframes; ++i) {
    367     IFrameLoader loader(current_browser_, i, GURL());
    368     iframe_urls_[i] = loader.iframe_url();
    369   }
    370 }
    371 
    372 void GeolocationBrowserTest::AddGeolocationWatch(bool wait_for_infobar) {
    373   GeolocationNotificationObserver notification_observer(wait_for_infobar);
    374   notification_observer.AddWatchAndWaitForNotification(
    375       current_browser_->tab_strip_model()->GetActiveWebContents()->
    376           GetRenderViewHost(),
    377       iframe_xpath());
    378   if (wait_for_infobar) {
    379     EXPECT_TRUE(notification_observer.has_infobar());
    380     infobar_ = notification_observer.infobar();
    381   }
    382 }
    383 
    384 void GeolocationBrowserTest::CheckGeoposition(double latitude,
    385                                               double longitude) {
    386   // Checks we have no error.
    387   CheckStringValueFromJavascript("0", "geoGetLastError()");
    388   CheckStringValueFromJavascript(base::DoubleToString(latitude),
    389                                  "geoGetLastPositionLatitude()");
    390   CheckStringValueFromJavascript(base::DoubleToString(longitude),
    391                                  "geoGetLastPositionLongitude()");
    392 }
    393 
    394 void GeolocationBrowserTest::SetInfoBarResponse(const GURL& requesting_url,
    395                                                 bool allowed) {
    396   WebContents* web_contents =
    397       current_browser_->tab_strip_model()->GetActiveWebContents();
    398   TabSpecificContentSettings* content_settings =
    399       TabSpecificContentSettings::FromWebContents(web_contents);
    400   const ContentSettingsUsagesState& usages_state =
    401       content_settings->geolocation_usages_state();
    402   size_t state_map_size = usages_state.state_map().size();
    403   ASSERT_TRUE(infobar_);
    404   LOG(WARNING) << "will set infobar response";
    405   {
    406     content::WindowedNotificationObserver observer(
    407         content::NOTIFICATION_LOAD_STOP,
    408         content::Source<NavigationController>(&web_contents->GetController()));
    409     if (allowed)
    410       infobar_->delegate()->AsConfirmInfoBarDelegate()->Accept();
    411     else
    412       infobar_->delegate()->AsConfirmInfoBarDelegate()->Cancel();
    413     observer.Wait();
    414   }
    415 
    416   InfoBarService::FromWebContents(web_contents)->RemoveInfoBar(infobar_);
    417   LOG(WARNING) << "infobar response set";
    418   infobar_ = NULL;
    419   EXPECT_GT(usages_state.state_map().size(), state_map_size);
    420   GURL requesting_origin(requesting_url.GetOrigin());
    421   EXPECT_EQ(1U, usages_state.state_map().count(requesting_origin));
    422   ContentSetting expected_setting =
    423         allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
    424   EXPECT_EQ(expected_setting,
    425             usages_state.state_map().find(requesting_origin)->second);
    426 }
    427 
    428 void GeolocationBrowserTest::CheckStringValueFromJavascriptForTab(
    429     const std::string& expected,
    430     const std::string& function,
    431     WebContents* web_contents) {
    432   std::string script(base::StringPrintf(
    433       "window.domAutomationController.send(%s)", function.c_str()));
    434   std::string result;
    435   ASSERT_TRUE(content::ExecuteScriptInFrameAndExtractString(
    436       web_contents, iframe_xpath_, script, &result));
    437   EXPECT_EQ(expected, result);
    438 }
    439 
    440 void GeolocationBrowserTest::CheckStringValueFromJavascript(
    441     const std::string& expected,
    442     const std::string& function) {
    443   CheckStringValueFromJavascriptForTab(
    444       expected, function,
    445       current_browser_->tab_strip_model()->GetActiveWebContents());
    446 }
    447 
    448 void GeolocationBrowserTest::NotifyGeoposition(double latitude,
    449                                                double longitude) {
    450   fake_latitude_ = latitude;
    451   fake_longitude_ = longitude;
    452   ui_test_utils::OverrideGeolocation(latitude, longitude);
    453   LOG(WARNING) << "MockLocationProvider listeners updated";
    454 }
    455 
    456 
    457 // Tests ----------------------------------------------------------------------
    458 
    459 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DisplaysPermissionBar) {
    460   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    461   AddGeolocationWatch(true);
    462 }
    463 
    464 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, Geoposition) {
    465   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    466   AddGeolocationWatch(true);
    467   SetInfoBarResponse(current_url(), true);
    468   CheckGeoposition(fake_latitude(), fake_longitude());
    469 }
    470 
    471 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest,
    472                        ErrorOnPermissionDenied) {
    473   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    474   AddGeolocationWatch(true);
    475   // Infobar was displayed, deny access and check for error code.
    476   SetInfoBarResponse(current_url(), false);
    477   CheckStringValueFromJavascript("1", "geoGetLastError()");
    478 }
    479 
    480 // See http://crbug.com/308358
    481 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, DISABLED_NoInfobarForSecondTab) {
    482   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    483   AddGeolocationWatch(true);
    484   SetInfoBarResponse(current_url(), true);
    485   // Disables further prompts from this tab.
    486   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
    487 
    488   // Checks infobar will not be created a second tab.
    489   ASSERT_TRUE(Initialize(INITIALIZATION_NEWTAB));
    490   AddGeolocationWatch(false);
    491   CheckGeoposition(fake_latitude(), fake_longitude());
    492 }
    493 
    494 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfobarForDeniedOrigin) {
    495   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    496   current_browser()->profile()->GetHostContentSettingsMap()->SetContentSetting(
    497       ContentSettingsPattern::FromURLNoWildcard(current_url()),
    498       ContentSettingsPattern::FromURLNoWildcard(current_url()),
    499       CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(), CONTENT_SETTING_BLOCK);
    500   AddGeolocationWatch(false);
    501   // Checks we have an error for this denied origin.
    502   CheckStringValueFromJavascript("1", "geoGetLastError()");
    503   // Checks infobar will not be created a second tab.
    504   ASSERT_TRUE(Initialize(INITIALIZATION_NEWTAB));
    505   AddGeolocationWatch(false);
    506   CheckStringValueFromJavascript("1", "geoGetLastError()");
    507 }
    508 
    509 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfobarForAllowedOrigin) {
    510   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    511   current_browser()->profile()->GetHostContentSettingsMap()->SetContentSetting(
    512       ContentSettingsPattern::FromURLNoWildcard(current_url()),
    513       ContentSettingsPattern::FromURLNoWildcard(current_url()),
    514       CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(), CONTENT_SETTING_ALLOW);
    515   // Checks no infobar will be created and there's no error callback.
    516   AddGeolocationWatch(false);
    517   CheckGeoposition(fake_latitude(), fake_longitude());
    518 }
    519 
    520 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfobarForOffTheRecord) {
    521   // First, check infobar will be created for regular profile
    522   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    523   AddGeolocationWatch(true);
    524   // Response will be persisted
    525   SetInfoBarResponse(current_url(), true);
    526   CheckGeoposition(fake_latitude(), fake_longitude());
    527   // Disables further prompts from this tab.
    528   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
    529   // Go incognito, and checks no infobar will be created.
    530   ASSERT_TRUE(Initialize(INITIALIZATION_OFFTHERECORD));
    531   AddGeolocationWatch(false);
    532   CheckGeoposition(fake_latitude(), fake_longitude());
    533 }
    534 
    535 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoLeakFromOffTheRecord) {
    536   // First, check infobar will be created for incognito profile.
    537   ASSERT_TRUE(Initialize(INITIALIZATION_OFFTHERECORD));
    538   AddGeolocationWatch(true);
    539   // Response won't be persisted.
    540   SetInfoBarResponse(current_url(), true);
    541   CheckGeoposition(fake_latitude(), fake_longitude());
    542   // Disables further prompts from this tab.
    543   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
    544   // Go to the regular profile, infobar will be created.
    545   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    546   AddGeolocationWatch(true);
    547   SetInfoBarResponse(current_url(), false);
    548   CheckStringValueFromJavascript("1", "geoGetLastError()");
    549 }
    550 
    551 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, IFramesWithFreshPosition) {
    552   set_html_for_tests("/geolocation/iframes_different_origin.html");
    553   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
    554   LoadIFrames(2);
    555   LOG(WARNING) << "frames loaded";
    556 
    557   set_iframe_xpath("//iframe[@id='iframe_0']");
    558   AddGeolocationWatch(true);
    559   SetInfoBarResponse(iframe_url(0), true);
    560   CheckGeoposition(fake_latitude(), fake_longitude());
    561   // Disables further prompts from this iframe.
    562   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
    563 
    564   // Test second iframe from a different origin with a cached geoposition will
    565   // create the infobar.
    566   set_iframe_xpath("//iframe[@id='iframe_1']");
    567   AddGeolocationWatch(true);
    568 
    569   // Back to the first frame, enable navigation and refresh geoposition.
    570   set_iframe_xpath("//iframe[@id='iframe_0']");
    571   CheckStringValueFromJavascript("1", "geoSetMaxNavigateCount(1)");
    572   double fresh_position_latitude = 3.17;
    573   double fresh_position_longitude = 4.23;
    574   content::WindowedNotificationObserver observer(
    575       content::NOTIFICATION_LOAD_STOP,
    576       content::Source<NavigationController>(
    577           &current_browser()->tab_strip_model()->GetActiveWebContents()->
    578               GetController()));
    579   NotifyGeoposition(fresh_position_latitude, fresh_position_longitude);
    580   observer.Wait();
    581   CheckGeoposition(fresh_position_latitude, fresh_position_longitude);
    582 
    583   // Disable navigation for this frame.
    584   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
    585 
    586   // Now go ahead an authorize the second frame.
    587   set_iframe_xpath("//iframe[@id='iframe_1']");
    588   // Infobar was displayed, allow access and check there's no error code.
    589   SetInfoBarResponse(iframe_url(1), true);
    590   LOG(WARNING) << "Checking position...";
    591   CheckGeoposition(fresh_position_latitude, fresh_position_longitude);
    592   LOG(WARNING) << "...done.";
    593 }
    594 
    595 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest,
    596                        IFramesWithCachedPosition) {
    597   set_html_for_tests("/geolocation/iframes_different_origin.html");
    598   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
    599   LoadIFrames(2);
    600 
    601   set_iframe_xpath("//iframe[@id='iframe_0']");
    602   AddGeolocationWatch(true);
    603   SetInfoBarResponse(iframe_url(0), true);
    604   CheckGeoposition(fake_latitude(), fake_longitude());
    605 
    606   // Refresh geoposition, but let's not yet create the watch on the second frame
    607   // so that it'll fetch from cache.
    608   double cached_position_latitude = 5.67;
    609   double cached_position_lognitude = 8.09;
    610   content::WindowedNotificationObserver observer(
    611       content::NOTIFICATION_LOAD_STOP,
    612       content::Source<NavigationController>(
    613           &current_browser()->tab_strip_model()->GetActiveWebContents()->
    614               GetController()));
    615   NotifyGeoposition(cached_position_latitude, cached_position_lognitude);
    616   observer.Wait();
    617   CheckGeoposition(cached_position_latitude, cached_position_lognitude);
    618 
    619   // Disable navigation for this frame.
    620   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
    621 
    622   // Now go ahead an authorize the second frame.
    623   set_iframe_xpath("//iframe[@id='iframe_1']");
    624   AddGeolocationWatch(true);
    625   // WebKit will use its cache, but we also broadcast a position shortly
    626   // afterwards. We're only interested in the first navigation for the success
    627   // callback from the cached position.
    628   CheckStringValueFromJavascript("1", "geoSetMaxNavigateCount(1)");
    629   SetInfoBarResponse(iframe_url(1), true);
    630   CheckGeoposition(cached_position_latitude, cached_position_lognitude);
    631 }
    632 
    633 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, CancelPermissionForFrame) {
    634   set_html_for_tests("/geolocation/iframes_different_origin.html");
    635   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
    636   LoadIFrames(2);
    637   LOG(WARNING) << "frames loaded";
    638 
    639   set_iframe_xpath("//iframe[@id='iframe_0']");
    640   AddGeolocationWatch(true);
    641   SetInfoBarResponse(iframe_url(0), true);
    642   CheckGeoposition(fake_latitude(), fake_longitude());
    643   // Disables further prompts from this iframe.
    644   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
    645 
    646   // Test second iframe from a different origin with a cached geoposition will
    647   // create the infobar.
    648   set_iframe_xpath("//iframe[@id='iframe_1']");
    649   AddGeolocationWatch(true);
    650 
    651   InfoBarService* infobar_service = InfoBarService::FromWebContents(
    652       current_browser()->tab_strip_model()->GetActiveWebContents());
    653   size_t num_infobars_before_cancel = infobar_service->infobar_count();
    654   // Change the iframe, and ensure the infobar is gone.
    655   IFrameLoader change_iframe_1(current_browser(), 1, current_url());
    656   size_t num_infobars_after_cancel = infobar_service->infobar_count();
    657   EXPECT_EQ(num_infobars_before_cancel, num_infobars_after_cancel + 1);
    658 }
    659 
    660 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, InvalidUrlRequest) {
    661   // Tests that an invalid URL (e.g. from a popup window) is rejected
    662   // correctly. Also acts as a regression test for http://crbug.com/40478
    663   set_html_for_tests("/geolocation/invalid_request_url.html");
    664   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    665   WebContents* original_tab =
    666       current_browser()->tab_strip_model()->GetActiveWebContents();
    667   CheckStringValueFromJavascript("1", "requestGeolocationFromInvalidUrl()");
    668   CheckStringValueFromJavascriptForTab("1", "isAlive()", original_tab);
    669 }
    670 
    671 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, NoInfoBarBeforeStart) {
    672   // See http://crbug.com/42789
    673   set_html_for_tests("/geolocation/iframes_different_origin.html");
    674   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
    675   LoadIFrames(2);
    676   LOG(WARNING) << "frames loaded";
    677 
    678   // Access navigator.geolocation, but ensure it won't request permission.
    679   set_iframe_xpath("//iframe[@id='iframe_1']");
    680   CheckStringValueFromJavascript("object", "geoAccessNavigatorGeolocation()");
    681 
    682   set_iframe_xpath("//iframe[@id='iframe_0']");
    683   AddGeolocationWatch(true);
    684   SetInfoBarResponse(iframe_url(0), true);
    685   CheckGeoposition(fake_latitude(), fake_longitude());
    686   CheckStringValueFromJavascript("0", "geoSetMaxNavigateCount(0)");
    687 
    688   // Permission should be requested after adding a watch.
    689   set_iframe_xpath("//iframe[@id='iframe_1']");
    690   AddGeolocationWatch(true);
    691   SetInfoBarResponse(iframe_url(1), true);
    692   CheckGeoposition(fake_latitude(), fake_longitude());
    693 }
    694 
    695 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, TwoWatchesInOneFrame) {
    696   set_html_for_tests("/geolocation/two_watches.html");
    697   ASSERT_TRUE(Initialize(INITIALIZATION_NONE));
    698   // First, set the JavaScript to navigate when it receives |final_position|.
    699   double final_position_latitude = 3.17;
    700   double final_position_longitude = 4.23;
    701   std::string script = base::StringPrintf(
    702       "window.domAutomationController.send(geoSetFinalPosition(%f, %f))",
    703       final_position_latitude, final_position_longitude);
    704   std::string js_result;
    705   EXPECT_TRUE(content::ExecuteScriptAndExtractString(
    706       current_browser()->tab_strip_model()->GetActiveWebContents(), script,
    707       &js_result));
    708   EXPECT_EQ(js_result, "ok");
    709 
    710   // Send a position which both geolocation watches will receive.
    711   AddGeolocationWatch(true);
    712   SetInfoBarResponse(current_url(), true);
    713   CheckGeoposition(fake_latitude(), fake_longitude());
    714 
    715   // The second watch will now have cancelled. Ensure an update still makes
    716   // its way through to the first watcher.
    717   content::WindowedNotificationObserver observer(
    718       content::NOTIFICATION_LOAD_STOP,
    719       content::Source<NavigationController>(
    720           &current_browser()->tab_strip_model()->GetActiveWebContents()->
    721               GetController()));
    722   NotifyGeoposition(final_position_latitude, final_position_longitude);
    723   observer.Wait();
    724   CheckGeoposition(final_position_latitude, final_position_longitude);
    725 }
    726 
    727 IN_PROC_BROWSER_TEST_F(GeolocationBrowserTest, TabDestroyed) {
    728   set_html_for_tests("/geolocation/tab_destroyed.html");
    729   ASSERT_TRUE(Initialize(INITIALIZATION_IFRAMES));
    730   LoadIFrames(3);
    731 
    732   set_iframe_xpath("//iframe[@id='iframe_0']");
    733   AddGeolocationWatch(true);
    734 
    735   set_iframe_xpath("//iframe[@id='iframe_1']");
    736   AddGeolocationWatch(false);
    737 
    738   set_iframe_xpath("//iframe[@id='iframe_2']");
    739   AddGeolocationWatch(false);
    740 
    741   std::string script =
    742       "window.domAutomationController.send(window.close());";
    743   bool result = content::ExecuteScript(
    744       current_browser()->tab_strip_model()->GetActiveWebContents(), script);
    745   EXPECT_EQ(result, true);
    746 }
    747