15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
69ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_match.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/extension_app_provider.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/url_database.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "components/metrics/proto/omnibox_event.pb.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using base::ASCIIToUTF16;
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ExtensionAppProviderTest : public testing::Test {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct test_data {
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16 input;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t num_results;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL output[3];
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionAppProviderTest()
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ui_thread_(content::BrowserThread::UI, &message_loop_),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        history_service_(NULL) { }
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ExtensionAppProviderTest() { }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void RunTest(test_data* keyword_cases,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               int num_cases);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForUI message_loop_;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ExtensionAppProvider> app_provider_;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestingProfile> profile_;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HistoryService* history_service_;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAppProviderTest::SetUp() {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_.reset(new TestingProfile());
48bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  ASSERT_TRUE(profile_->CreateHistoryService(true, false));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  profile_->BlockUntilHistoryProcessesPendingRequests();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  history_service_ =
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HistoryServiceFactory::GetForProfile(profile_.get(),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           Profile::EXPLICIT_ACCESS);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  app_provider_ = new ExtensionAppProvider(NULL, profile_.get());
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TestExtensionApp {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* app_name;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* launch_url;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool should_match_against_launch_url;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* title;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int typed_count;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } kExtensionApps[] = {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"COYB", "http://asdf/",            true,  "COYB", 7},
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"NSNO", "http://fdsa/",            true,  "NSNO", 2},
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {"APPP", "chrome-extension://xyz/", false, "APPP", 2},
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  history::URLDatabase* url_db = history_service_->InMemoryDatabase();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kExtensionApps); ++i) {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Populate the Extension Apps list.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionAppProvider::ExtensionApp extension_app = {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASCIIToUTF16(kExtensionApps[i].app_name),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASCIIToUTF16(kExtensionApps[i].launch_url),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kExtensionApps[i].should_match_against_launch_url
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_provider_->AddExtensionAppForTesting(extension_app);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Populate the InMemoryDatabase.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    history::URLRow info(GURL(kExtensionApps[i].launch_url));
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    info.set_title(base::UTF8ToUTF16(kExtensionApps[i].title));
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    info.set_typed_count(kExtensionApps[i].typed_count);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url_db->AddURL(info);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAppProviderTest::RunTest(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test_data* keyword_cases,
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int num_cases) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ACMatches matches;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < num_cases; ++i) {
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    AutocompleteInput input(keyword_cases[i].input, base::string16::npos,
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                            base::string16(), GURL(),
946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                            metrics::OmniboxEventProto::INVALID_SPEC, true,
950529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                            false, true, true);
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_provider_->Start(input, false);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(app_provider_->done());
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    matches = app_provider_->matches();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(keyword_cases[i].num_results, matches.size())
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        << ASCIIToUTF16("Input was: ") + keyword_cases[i].input;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (matches.size() == keyword_cases[i].num_results) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t j = 0; j < keyword_cases[i].num_results; ++j)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        EXPECT_EQ(keyword_cases[i].output[j], matches[j].destination_url);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionAppProviderTest, BasicMatching) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  test_data edit_cases[] = {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Searching for a nonexistent value should give nothing.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {ASCIIToUTF16("Not Found"),       0, { GURL() }},
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The letter 'o' appears in both extension apps.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {ASCIIToUTF16("o"),               2, { GURL("http://asdf/"),
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           GURL("http://fdsa/") }},
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The string 'co' appears in one extension app.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {ASCIIToUTF16("co"),              1, { GURL("http://asdf/") }},
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Try with URL matching.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {ASCIIToUTF16("http://asdf/"),    1, { GURL("http://asdf/") }},
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {ASCIIToUTF16("http://fdsa/"),    1, { GURL("http://fdsa/") }},
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // "xyz" appears in a launch URL, but we're not matching against it.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {ASCIIToUTF16("xyz"),             0, { GURL() }},
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // But it should be matcheable by title.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {ASCIIToUTF16("APPP"),            1, { GURL("chrome-extension://xyz/") }},
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunTest(edit_cases, ARRAYSIZE_UNSAFE(edit_cases));
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(ExtensionAppProviderTest, CreateMatchSanitize) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct TestData {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* name;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* match_contents;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } cases[] = {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Test", "Test" },
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Test \n Test", "Test  Test" },
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { "Test\r\t\nTest", "TestTest" },
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AutocompleteInput input(ASCIIToUTF16("Test"), base::string16::npos,
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          base::string16(), GURL(),
1456d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                          metrics::OmniboxEventProto::INVALID_SPEC, true, true,
1460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                          true, false);
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 url(ASCIIToUTF16("http://example.com"));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionAppProvider::ExtensionApp extension_app =
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        {ASCIIToUTF16(cases[i].name), url, true};
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AutocompleteMatch match =
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        app_provider_->CreateAutocompleteMatch(input,
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               extension_app,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               0,
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                               base::string16::npos);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ASCIIToUTF16(cases[i].match_contents), match.contents);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
159