Home | History | Annotate | Download | only in omnibox
      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 "base/strings/utf_string_conversions.h"
      6 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
      7 #include "chrome/browser/search_engines/template_url_service_factory.h"
      8 #include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
      9 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
     10 #include "chrome/browser/ui/omnibox/omnibox_view.h"
     11 #include "chrome/browser/ui/toolbar/test_toolbar_model.h"
     12 #include "chrome/test/base/testing_profile.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 
     15 using content::WebContents;
     16 
     17 namespace {
     18 
     19 class TestingOmniboxView : public OmniboxView {
     20  public:
     21   explicit TestingOmniboxView(OmniboxEditController* controller)
     22       : OmniboxView(NULL, controller, NULL) {}
     23 
     24   // OmniboxView:
     25   virtual void SaveStateToTab(WebContents* tab) OVERRIDE {}
     26   virtual void OnTabChanged(const WebContents* web_contents) OVERRIDE {}
     27   virtual void Update() OVERRIDE {}
     28   virtual void OpenMatch(const AutocompleteMatch& match,
     29                          WindowOpenDisposition disposition,
     30                          const GURL& alternate_nav_url,
     31                          size_t selected_line) OVERRIDE {}
     32   virtual base::string16 GetText() const OVERRIDE { return text_; }
     33   virtual void SetUserText(const base::string16& text,
     34                            const base::string16& display_text,
     35                            bool update_popup) OVERRIDE {
     36     text_ = display_text;
     37   }
     38   virtual void SetWindowTextAndCaretPos(const base::string16& text,
     39                                         size_t caret_pos,
     40                                         bool update_popup,
     41                                         bool notify_text_changed) OVERRIDE {
     42     text_ = text;
     43   }
     44   virtual void SetForcedQuery() OVERRIDE {}
     45   virtual bool IsSelectAll() const OVERRIDE { return false; }
     46   virtual bool DeleteAtEndPressed() OVERRIDE { return false; }
     47   virtual void GetSelectionBounds(size_t* start, size_t* end) const OVERRIDE {}
     48   virtual void SelectAll(bool reversed) OVERRIDE {}
     49   virtual void RevertAll() OVERRIDE {}
     50   virtual void UpdatePopup() OVERRIDE {}
     51   virtual void SetFocus() OVERRIDE {}
     52   virtual void ApplyCaretVisibility() OVERRIDE {}
     53   virtual void OnTemporaryTextMaybeChanged(
     54       const base::string16& display_text,
     55       bool save_original_selection,
     56       bool notify_text_changed) OVERRIDE {
     57     text_ = display_text;
     58   }
     59   virtual bool OnInlineAutocompleteTextMaybeChanged(
     60       const base::string16& display_text, size_t user_text_length) OVERRIDE {
     61     const bool text_changed = text_ != display_text;
     62     text_ = display_text;
     63     inline_autocomplete_text_ = display_text.substr(user_text_length);
     64     return text_changed;
     65   }
     66   virtual void OnInlineAutocompleteTextCleared() OVERRIDE {
     67     inline_autocomplete_text_.clear();
     68   }
     69   virtual void OnRevertTemporaryText() OVERRIDE {}
     70   virtual void OnBeforePossibleChange() OVERRIDE {}
     71   virtual bool OnAfterPossibleChange() OVERRIDE { return false; }
     72   virtual gfx::NativeView GetNativeView() const OVERRIDE { return NULL; }
     73   virtual gfx::NativeView GetRelativeWindowForPopup() const OVERRIDE {
     74     return NULL;
     75   }
     76   virtual void SetGrayTextAutocompletion(
     77       const base::string16& input) OVERRIDE {}
     78   virtual base::string16 GetGrayTextAutocompletion() const OVERRIDE {
     79     return base::string16();
     80   }
     81   virtual int GetTextWidth() const OVERRIDE { return 0; }
     82   virtual int GetWidth() const OVERRIDE { return 0; }
     83   virtual bool IsImeComposing() const OVERRIDE { return false; }
     84 #if defined(TOOLKIT_VIEWS)
     85   virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE {
     86     return 0;
     87   }
     88 #endif
     89   virtual int GetOmniboxTextLength() const OVERRIDE { return 0; }
     90   virtual void EmphasizeURLComponents() OVERRIDE { }
     91 
     92   const base::string16& inline_autocomplete_text() const {
     93     return inline_autocomplete_text_;
     94   }
     95 
     96  private:
     97   base::string16 text_;
     98   base::string16 inline_autocomplete_text_;
     99 
    100   DISALLOW_COPY_AND_ASSIGN(TestingOmniboxView);
    101 };
    102 
    103 class TestingOmniboxEditController : public OmniboxEditController {
    104  public:
    105   explicit TestingOmniboxEditController(ToolbarModel* toolbar_model)
    106       : OmniboxEditController(NULL),
    107         toolbar_model_(toolbar_model) {
    108   }
    109 
    110   // OmniboxEditController:
    111   virtual void Update(const content::WebContents* contents) OVERRIDE {}
    112   virtual void OnChanged() OVERRIDE {}
    113   virtual void OnSetFocus() OVERRIDE {}
    114   virtual InstantController* GetInstant() OVERRIDE { return NULL; }
    115   virtual WebContents* GetWebContents() OVERRIDE { return NULL; }
    116   virtual ToolbarModel* GetToolbarModel() OVERRIDE { return toolbar_model_; }
    117   virtual const ToolbarModel* GetToolbarModel() const OVERRIDE {
    118     return toolbar_model_;
    119   }
    120 
    121  private:
    122   ToolbarModel* toolbar_model_;
    123 
    124   DISALLOW_COPY_AND_ASSIGN(TestingOmniboxEditController);
    125 };
    126 
    127 }  // namespace
    128 
    129 class AutocompleteEditTest : public ::testing::Test {
    130  public:
    131   TestToolbarModel* toolbar_model() { return &toolbar_model_; }
    132 
    133  private:
    134   TestToolbarModel toolbar_model_;
    135 };
    136 
    137 // Tests various permutations of AutocompleteModel::AdjustTextForCopy.
    138 TEST_F(AutocompleteEditTest, AdjustTextForCopy) {
    139   struct Data {
    140     const char* perm_text;
    141     const int sel_start;
    142     const bool is_all_selected;
    143     const char* input;
    144     const char* expected_output;
    145     const bool write_url;
    146     const char* expected_url;
    147     const bool extracted_search_terms;
    148   } input[] = {
    149     // Test that http:// is inserted if all text is selected.
    150     { "a.de/b", 0, true, "a.de/b", "http://a.de/b", true, "http://a.de/b",
    151       false },
    152 
    153     // Test that http:// is inserted if the host is selected.
    154     { "a.de/b", 0, false, "a.de/", "http://a.de/", true, "http://a.de/",
    155       false },
    156 
    157     // Tests that http:// is inserted if the path is modified.
    158     { "a.de/b", 0, false, "a.de/c", "http://a.de/c", true, "http://a.de/c",
    159       false },
    160 
    161     // Tests that http:// isn't inserted if the host is modified.
    162     { "a.de/b", 0, false, "a.com/b", "a.com/b", false, "", false },
    163 
    164     // Tests that http:// isn't inserted if the start of the selection is 1.
    165     { "a.de/b", 1, false, "a.de/b", "a.de/b", false, "", false },
    166 
    167     // Tests that http:// isn't inserted if a portion of the host is selected.
    168     { "a.de/", 0, false, "a.d", "a.d", false, "", false },
    169 
    170     // Tests that http:// isn't inserted for an https url after the user nukes
    171     // https.
    172     { "https://a.com/", 0, false, "a.com/", "a.com/", false, "", false },
    173 
    174     // Tests that http:// isn't inserted if the user adds to the host.
    175     { "a.de/", 0, false, "a.de.com/", "a.de.com/", false, "", false },
    176 
    177     // Tests that we don't get double http if the user manually inserts http.
    178     { "a.de/", 0, false, "http://a.de/", "http://a.de/", true, "http://a.de/",
    179       false },
    180 
    181     // Makes sure intranet urls get 'http://' prefixed to them.
    182     { "b/foo", 0, true, "b/foo", "http://b/foo", true, "http://b/foo", false },
    183 
    184     // Verifies a search term 'foo' doesn't end up with http.
    185     { "www.google.com/search?", 0, false, "foo", "foo", false, "", false },
    186 
    187     // Makes sure extracted search terms are not modified.
    188     { "www.google.com/webhp?", 0, true, "hello world", "hello world", false,
    189       "", true },
    190   };
    191   TestingOmniboxEditController controller(toolbar_model());
    192   TestingOmniboxView view(&controller);
    193   TestingProfile profile;
    194   // NOTE: The TemplateURLService must be created before the
    195   // AutocompleteClassifier so that the SearchProvider gets a non-NULL
    196   // TemplateURLService at construction time.
    197   TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
    198       &profile, &TemplateURLServiceFactory::BuildInstanceFor);
    199   AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse(
    200       &profile, &AutocompleteClassifierFactory::BuildInstanceFor);
    201   OmniboxEditModel model(&view, &controller, &profile);
    202 
    203   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(input); ++i) {
    204     toolbar_model()->set_text(ASCIIToUTF16(input[i].perm_text));
    205     model.UpdatePermanentText();
    206 
    207     toolbar_model()->set_perform_search_term_replacement(
    208         input[i].extracted_search_terms);
    209 
    210     base::string16 result = ASCIIToUTF16(input[i].input);
    211     GURL url;
    212     bool write_url;
    213     model.AdjustTextForCopy(input[i].sel_start, input[i].is_all_selected,
    214                             &result, &url, &write_url);
    215     EXPECT_EQ(ASCIIToUTF16(input[i].expected_output), result) << "@: " << i;
    216     EXPECT_EQ(input[i].write_url, write_url) << " @" << i;
    217     if (write_url)
    218       EXPECT_EQ(input[i].expected_url, url.spec()) << " @" << i;
    219   }
    220 }
    221 
    222 // This test causes resource leak.  Disabled until it's fixed.
    223 // TODO(yukishiino): Fix the leak.
    224 TEST_F(AutocompleteEditTest, DISABLED_InlineAutocompleteText) {
    225   TestingOmniboxEditController controller(toolbar_model());
    226   TestingOmniboxView view(&controller);
    227   TestingProfile profile;
    228   // NOTE: The TemplateURLService must be created before the
    229   // AutocompleteClassifier so that the SearchProvider gets a non-NULL
    230   // TemplateURLService at construction time.
    231   TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
    232       &profile, &TemplateURLServiceFactory::BuildInstanceFor);
    233   AutocompleteClassifierFactory::GetInstance()->SetTestingFactoryAndUse(
    234       &profile, &AutocompleteClassifierFactory::BuildInstanceFor);
    235   OmniboxEditModel model(&view, &controller, &profile);
    236 
    237   // Test if the model updates the inline autocomplete text in the view.
    238   EXPECT_EQ(base::string16(), view.inline_autocomplete_text());
    239   model.SetUserText(UTF8ToUTF16("he"));
    240   model.OnPopupDataChanged(UTF8ToUTF16("llo"), NULL, base::string16(), false);
    241   EXPECT_EQ(UTF8ToUTF16("hello"), view.GetText());
    242   EXPECT_EQ(UTF8ToUTF16("llo"), view.inline_autocomplete_text());
    243 
    244   model.OnAfterPossibleChange(UTF8ToUTF16("he"), UTF8ToUTF16("hel"), 3, 3,
    245                               false, true, false, true);
    246   EXPECT_EQ(base::string16(), view.inline_autocomplete_text());
    247   model.OnPopupDataChanged(UTF8ToUTF16("lo"), NULL, base::string16(), false);
    248   EXPECT_EQ(UTF8ToUTF16("hello"), view.GetText());
    249   EXPECT_EQ(UTF8ToUTF16("lo"), view.inline_autocomplete_text());
    250 
    251   model.Revert();
    252   EXPECT_EQ(base::string16(), view.GetText());
    253   EXPECT_EQ(base::string16(), view.inline_autocomplete_text());
    254 
    255   model.SetUserText(UTF8ToUTF16("he"));
    256   model.OnPopupDataChanged(UTF8ToUTF16("llo"), NULL, base::string16(), false);
    257   EXPECT_EQ(UTF8ToUTF16("hello"), view.GetText());
    258   EXPECT_EQ(UTF8ToUTF16("llo"), view.inline_autocomplete_text());
    259 
    260   model.AcceptTemporaryTextAsUserText();
    261   EXPECT_EQ(UTF8ToUTF16("hello"), view.GetText());
    262   EXPECT_EQ(base::string16(), view.inline_autocomplete_text());
    263 }
    264