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