Home | History | Annotate | Download | only in toolbar
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/toolbar/toolbar_model.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/command_line.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
     12 #include "chrome/browser/search/search.h"
     13 #include "chrome/browser/search_engines/search_terms_data.h"
     14 #include "chrome/browser/search_engines/template_url.h"
     15 #include "chrome/browser/search_engines/template_url_service.h"
     16 #include "chrome/browser/search_engines/template_url_service_factory.h"
     17 #include "chrome/browser/ui/browser.h"
     18 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     19 #include "chrome/browser/ui/toolbar/toolbar_model.h"
     20 #include "chrome/common/chrome_switches.h"
     21 #include "chrome/test/base/browser_with_test_window_test.h"
     22 #include "content/public/browser/navigation_entry.h"
     23 #include "content/public/browser/render_process_host.h"
     24 #include "content/public/browser/web_contents.h"
     25 #include "content/public/common/ssl_status.h"
     26 #include "content/public/common/url_constants.h"
     27 #include "net/base/escape.h"
     28 
     29 
     30 // Test data ------------------------------------------------------------------
     31 
     32 namespace {
     33 
     34 struct TestItem {
     35   GURL url;
     36   string16 expected_text;
     37   // The expected text to display when query extraction is inactive.
     38   string16 expected_replace_text_inactive;
     39   // The expected text to display when query extraction is active.
     40   string16 expected_replace_text_active;
     41   bool would_replace;
     42   bool should_display;
     43 } test_items[] = {
     44   {
     45     GURL("view-source:http://www.google.com"),
     46     ASCIIToUTF16("view-source:www.google.com"),
     47     ASCIIToUTF16("view-source:www.google.com"),
     48     ASCIIToUTF16("view-source:www.google.com"),
     49     false,
     50     true
     51   },
     52   {
     53     GURL("view-source:chrome://newtab/"),
     54     ASCIIToUTF16("view-source:chrome://newtab"),
     55     ASCIIToUTF16("view-source:chrome://newtab"),
     56     ASCIIToUTF16("view-source:chrome://newtab"),
     57     false,
     58     true
     59   },
     60   {
     61     GURL("chrome-extension://monkey/balls.html"),
     62     ASCIIToUTF16("chrome-extension://monkey/balls.html"),
     63     ASCIIToUTF16("chrome-extension://monkey/balls.html"),
     64     ASCIIToUTF16("chrome-extension://monkey/balls.html"),
     65     false,
     66     true
     67   },
     68   {
     69     GURL("chrome://newtab/"),
     70     string16(),
     71     string16(),
     72     string16(),
     73     false,
     74     false
     75   },
     76   {
     77     GURL(content::kAboutBlankURL),
     78     ASCIIToUTF16(content::kAboutBlankURL),
     79     ASCIIToUTF16(content::kAboutBlankURL),
     80     ASCIIToUTF16(content::kAboutBlankURL),
     81     false,
     82     true
     83   },
     84   {
     85     GURL("http://searchurl/?q=tractor+supply"),
     86     ASCIIToUTF16("searchurl/?q=tractor+supply"),
     87     ASCIIToUTF16("searchurl/?q=tractor+supply"),
     88     ASCIIToUTF16("searchurl/?q=tractor+supply"),
     89     false,
     90     true
     91   },
     92   {
     93     GURL("http://google.com/search?q=tractor+supply&espv=1"),
     94     ASCIIToUTF16("google.com/search?q=tractor+supply&espv=1"),
     95     ASCIIToUTF16("google.com/search?q=tractor+supply&espv=1"),
     96     ASCIIToUTF16("google.com/search?q=tractor+supply&espv=1"),
     97     false,
     98     true
     99   },
    100   {
    101     GURL("https://google.ca/search?q=tractor+supply"),
    102     ASCIIToUTF16("https://google.ca/search?q=tractor+supply"),
    103     ASCIIToUTF16("https://google.ca/search?q=tractor+supply"),
    104     ASCIIToUTF16("https://google.ca/search?q=tractor+supply"),
    105     false,
    106     true
    107   },
    108   {
    109     GURL("https://google.com/search?q=tractor+supply"),
    110     ASCIIToUTF16("https://google.com/search?q=tractor+supply"),
    111     ASCIIToUTF16("https://google.com/search?q=tractor+supply"),
    112     ASCIIToUTF16("https://google.com/search?q=tractor+supply"),
    113     false,
    114     true
    115   },
    116   {
    117     GURL("https://google.com/search?q=tractor+supply&espv=1"),
    118     ASCIIToUTF16("https://google.com/search?q=tractor+supply&espv=1"),
    119     ASCIIToUTF16("https://google.com/search?q=tractor+supply&espv=1"),
    120     ASCIIToUTF16("tractor supply"),
    121     true,
    122     true
    123   },
    124   {
    125     GURL("https://google.com/search?q=tractorsupply.com&espv=1"),
    126     ASCIIToUTF16("https://google.com/search?q=tractorsupply.com&espv=1"),
    127     ASCIIToUTF16("https://google.com/search?q=tractorsupply.com&espv=1"),
    128     ASCIIToUTF16("tractorsupply.com"),
    129     true,
    130     true
    131   },
    132   {
    133     GURL("https://google.com/search?q=ftp://tractorsupply.ie&espv=1"),
    134     ASCIIToUTF16("https://google.com/search?q=ftp://tractorsupply.ie&espv=1"),
    135     ASCIIToUTF16("https://google.com/search?q=ftp://tractorsupply.ie&espv=1"),
    136     ASCIIToUTF16("ftp://tractorsupply.ie"),
    137     true,
    138     true
    139   },
    140 };
    141 
    142 }  // namespace
    143 
    144 
    145 // ToolbarModelTest -----------------------------------------------------------
    146 
    147 class ToolbarModelTest : public BrowserWithTestWindowTest {
    148  public:
    149   ToolbarModelTest();
    150   virtual ~ToolbarModelTest();
    151 
    152   // BrowserWithTestWindowTest:
    153   virtual void SetUp() OVERRIDE;
    154 
    155  protected:
    156   void ResetDefaultTemplateURL();
    157   void NavigateAndCheckText(const GURL& url,
    158                             const string16& expected_text,
    159                             const string16& expected_replace_text,
    160                             bool would_replace,
    161                             bool should_display);
    162 
    163  private:
    164   void ResetTemplateURLForInstant(const GURL& instant_url);
    165   void NavigateAndCheckTextImpl(const GURL& url,
    166                                 bool can_replace,
    167                                 const string16 expected_text,
    168                                 bool would_replace,
    169                                 bool should_display);
    170 
    171   DISALLOW_COPY_AND_ASSIGN(ToolbarModelTest);
    172 };
    173 
    174 ToolbarModelTest::ToolbarModelTest() {
    175 }
    176 
    177 ToolbarModelTest::~ToolbarModelTest() {
    178 }
    179 
    180 void ToolbarModelTest::SetUp() {
    181   BrowserWithTestWindowTest::SetUp();
    182   TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
    183       profile(), &TemplateURLServiceFactory::BuildInstanceFor);
    184   AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse(
    185       profile(), &AutocompleteClassifierFactory::BuildInstanceFor);
    186   UIThreadSearchTermsData::SetGoogleBaseURL("http://google.com/");
    187 }
    188 
    189 void ToolbarModelTest::ResetDefaultTemplateURL() {
    190   ResetTemplateURLForInstant(GURL("http://does/not/exist"));
    191 }
    192 
    193 void ToolbarModelTest::NavigateAndCheckText(
    194     const GURL& url,
    195     const string16& expected_text,
    196     const string16& expected_replace_text,
    197     bool would_replace,
    198     bool should_display) {
    199   NavigateAndCheckTextImpl(url, false, expected_text, would_replace,
    200                            should_display);
    201   NavigateAndCheckTextImpl(url, true, expected_replace_text, would_replace,
    202                            should_display);
    203 }
    204 
    205 void ToolbarModelTest::ResetTemplateURLForInstant(const GURL& instant_url) {
    206   TemplateURLData data;
    207   data.short_name = ASCIIToUTF16("Google");
    208   data.SetURL("{google:baseURL}search?q={searchTerms}");
    209   data.instant_url = instant_url.spec();
    210   data.search_terms_replacement_key = "{google:instantExtendedEnabledKey}";
    211   TemplateURL* search_template_url = new TemplateURL(profile(), data);
    212   TemplateURLService* template_url_service =
    213       TemplateURLServiceFactory::GetForProfile(profile());
    214   template_url_service->Add(search_template_url);
    215   template_url_service->SetDefaultSearchProvider(search_template_url);
    216   ASSERT_NE(0, search_template_url->id());
    217   template_url_service->Load();
    218 }
    219 
    220 void ToolbarModelTest::NavigateAndCheckTextImpl(const GURL& url,
    221                                                 bool can_replace,
    222                                                 const string16 expected_text,
    223                                                 bool would_replace,
    224                                                 bool should_display) {
    225   // The URL being navigated to should be treated as the Instant URL. Else
    226   // there will be no search term extraction.
    227   ResetTemplateURLForInstant(url);
    228 
    229   // Check while loading.
    230   content::NavigationController* controller =
    231       &browser()->tab_strip_model()->GetWebContentsAt(0)->GetController();
    232   controller->LoadURL(url, content::Referrer(), content::PAGE_TRANSITION_LINK,
    233                       std::string());
    234   ToolbarModel* toolbar_model = browser()->toolbar_model();
    235   EXPECT_EQ(should_display, toolbar_model->ShouldDisplayURL());
    236   EXPECT_EQ(expected_text, toolbar_model->GetText(can_replace));
    237   EXPECT_EQ(would_replace,
    238             toolbar_model->WouldReplaceSearchURLWithSearchTerms(false));
    239 
    240   // Check after commit.
    241   CommitPendingLoad(controller);
    242   // Fake a secure connection for HTTPS URLs, or the toolbar will refuse to
    243   // extract search terms.
    244   if (url.SchemeIsSecure()) {
    245     controller->GetVisibleEntry()->GetSSL().security_style =
    246         content::SECURITY_STYLE_AUTHENTICATED;
    247   }
    248   EXPECT_EQ(should_display, toolbar_model->ShouldDisplayURL());
    249   EXPECT_EQ(expected_text, toolbar_model->GetText(can_replace));
    250   EXPECT_EQ(would_replace,
    251             toolbar_model->WouldReplaceSearchURLWithSearchTerms(false));
    252 
    253   // Now pretend the user started modifying the omnibox.
    254   toolbar_model->SetInputInProgress(true);
    255   EXPECT_FALSE(toolbar_model->WouldReplaceSearchURLWithSearchTerms(false));
    256   EXPECT_EQ(would_replace,
    257             toolbar_model->WouldReplaceSearchURLWithSearchTerms(true));
    258 
    259   // Tell the ToolbarModel that the user has stopped editing.  This prevents
    260   // this function from having side effects.
    261   toolbar_model->SetInputInProgress(false);
    262 }
    263 
    264 
    265 // Actual tests ---------------------------------------------------------------
    266 
    267 // Test that we don't replace any URLs when the query extraction is disabled.
    268 TEST_F(ToolbarModelTest, ShouldDisplayURLQueryExtractionDisabled) {
    269   ASSERT_FALSE(chrome::IsQueryExtractionEnabled())
    270       << "This test expects query extraction to be disabled.";
    271   AddTab(browser(), GURL(content::kAboutBlankURL));
    272   for (size_t i = 0; i < arraysize(test_items); ++i) {
    273     const TestItem& test_item = test_items[i];
    274     NavigateAndCheckText(test_item.url, test_item.expected_text,
    275                          test_item.expected_replace_text_inactive, false,
    276                          test_item.should_display);
    277   }
    278 }
    279 
    280 // Test that we replace URLs when the query extraction API is enabled.
    281 TEST_F(ToolbarModelTest, ShouldDisplayURLQueryExtractionEnabled) {
    282   chrome::EnableInstantExtendedAPIForTesting();
    283   AddTab(browser(), GURL(content::kAboutBlankURL));
    284   for (size_t i = 0; i < arraysize(test_items); ++i) {
    285     const TestItem& test_item = test_items[i];
    286     NavigateAndCheckText(test_item.url, test_item.expected_text,
    287                          test_item.expected_replace_text_active,
    288                          test_item.would_replace,
    289                          test_item.should_display);
    290   }
    291 }
    292 
    293 // Verify that search terms are extracted while the page is loading.
    294 TEST_F(ToolbarModelTest, SearchTermsWhileLoading) {
    295   chrome::EnableInstantExtendedAPIForTesting();
    296   ResetDefaultTemplateURL();
    297   AddTab(browser(), GURL(content::kAboutBlankURL));
    298 
    299   // While loading, we should be willing to extract search terms.
    300   content::NavigationController* controller =
    301       &browser()->tab_strip_model()->GetWebContentsAt(0)->GetController();
    302   controller->LoadURL(GURL("https://google.com/search?q=tractor+supply&espv=1"),
    303                       content::Referrer(), content::PAGE_TRANSITION_LINK,
    304                       std::string());
    305   ToolbarModel* toolbar_model = browser()->toolbar_model();
    306   controller->GetVisibleEntry()->GetSSL().security_style =
    307       content::SECURITY_STYLE_UNKNOWN;
    308   EXPECT_TRUE(toolbar_model->WouldReplaceSearchURLWithSearchTerms(false));
    309 
    310   // When done loading, we shouldn't extract search terms if we didn't get an
    311   // authenticated connection.
    312   CommitPendingLoad(controller);
    313   controller->GetVisibleEntry()->GetSSL().security_style =
    314       content::SECURITY_STYLE_UNKNOWN;
    315   EXPECT_FALSE(toolbar_model->WouldReplaceSearchURLWithSearchTerms(false));
    316 }
    317 
    318 // When the Google base URL is overridden on the command line, we should extract
    319 // search terms from URLs that start with that base URL even when they're not
    320 // secure.
    321 TEST_F(ToolbarModelTest, GoogleBaseURL) {
    322   chrome::EnableInstantExtendedAPIForTesting();
    323   AddTab(browser(), GURL(content::kAboutBlankURL));
    324 
    325   // If the Google base URL wasn't specified on the command line, then if it's
    326   // HTTP, we should not extract search terms.
    327   UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/");
    328   NavigateAndCheckText(
    329       GURL("http://www.foo.com/search?q=tractor+supply&espv=1"),
    330       ASCIIToUTF16("www.foo.com/search?q=tractor+supply&espv=1"),
    331       ASCIIToUTF16("www.foo.com/search?q=tractor+supply&espv=1"), false,
    332       true);
    333 
    334   // The same URL, when specified on the command line, should allow search term
    335   // extraction.
    336   UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
    337   CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
    338                                                       "http://www.foo.com/");
    339   NavigateAndCheckText(
    340       GURL("http://www.foo.com/search?q=tractor+supply&espv=1"),
    341       ASCIIToUTF16("www.foo.com/search?q=tractor+supply&espv=1"),
    342       ASCIIToUTF16("tractor supply"), true, true);
    343 }
    344