people_provider_browsertest.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1// Copyright 2013 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/basictypes.h"
8#include "base/bind.h"
9#include "base/command_line.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/run_loop.h"
12#include "base/strings/utf_string_conversions.h"
13#include "chrome/browser/profiles/profile_manager.h"
14#include "chrome/browser/ui/app_list/search/chrome_search_result.h"
15#include "chrome/browser/ui/app_list/search/people/people_provider.h"
16#include "chrome/common/chrome_switches.h"
17#include "chrome/test/base/in_process_browser_test.h"
18#include "content/public/browser/browser_thread.h"
19#include "net/test/embedded_test_server/embedded_test_server.h"
20#include "net/test/embedded_test_server/http_request.h"
21#include "net/test/embedded_test_server/http_response.h"
22
23using content::BrowserThread;
24using net::test_server::BasicHttpResponse;
25using net::test_server::HttpRequest;
26using net::test_server::HttpResponse;
27using net::test_server::EmbeddedTestServer;
28
29namespace app_list {
30namespace test {
31namespace {
32
33// Mock results.
34const char kOneResult[] = "{"
35    "\"items\":["
36      "{"
37        "\"person\" : {"
38          "\"id\": \"1\","
39          "\"names\" : [{"
40            "\"displayName\": \"first person\""
41          "}],"
42          "\"images\" : [{"
43            "\"url\": \"http://host/icon\""
44          "}],"
45          "\"sortKeys\" : {"
46            "\"interactionRank\": \"0.98\""
47          "}"
48        "}"
49      "}"
50    "]}";
51
52const char kThreeValidResults[] = "{"
53    "\"items\":["
54      "{"
55        "\"person\" : {"
56          "\"id\": \"1\","
57          "\"names\" : [{"
58            "\"displayName\": \"first person\""
59          "}],"
60          "\"images\" : [{"
61            "\"url\": \"http://host/icon\""
62          "}],"
63          "\"sortKeys\" : {"
64            "\"interactionRank\": \"0.98\""
65          "}"
66        "}"
67      "},"
68      "{"
69        "\"person\" : {"
70          "\"id\": \"2\","
71          "\"names\" : [{"
72            "\"displayName\": \"second person\""
73          "}],"
74          "\"images\" : [{"
75            "\"url\": \"http://host/icon\""
76          "}],"
77          "\"sortKeys\" : {"
78            "\"interactionRank\": \"0.84\""
79          "}"
80        "}"
81      "},"
82      "{"
83        "\"person\" : {"
84          "\"id\": \"3\","
85          "\"names\" : [{"
86            "\"displayName\": \"third person\""
87          "}],"
88          "\"images\" : [{"
89            "\"url\": \"http://host/icon\""
90          "}],"
91          "\"sortKeys\" : {"
92            "\"interactionRank\": \"0.67\""
93          "}"
94        "}"
95      "},"
96      "{"
97        "\"person\" : {"
98          "\"id\": \"4\","
99          "\"names\" : [{"
100            "\"displayName\": \"fourth person\""
101          "}],"
102          "\"images\" : [{"
103            "\"url\": \"http://host/icon\""
104          "}],"
105          "\"sortKeys\" : {"
106            "\"interactionRank\": \"0.0\""
107          "}"
108        "}"
109      "},"
110      "{"
111        "\"person\" : {"
112          "\"id\": \"5\","
113          "\"names\" : [{"
114            "\"displayName\": \"fifth person\""
115          "}],"
116          // Images field is missing on purpose.
117          "\"sortKeys\" : {"
118            "\"interactionRank\": \"0.98\""
119          "}"
120        "}"
121      "}"
122    "]}";
123
124}  // namespace
125
126class PeopleProviderTest : public InProcessBrowserTest {
127 public:
128  PeopleProviderTest() {}
129  virtual ~PeopleProviderTest() {}
130
131  // InProcessBrowserTest overrides:
132  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
133    command_line->AppendSwitch(switches::kEnablePeopleSearch);
134  }
135
136  virtual void SetUpOnMainThread() OVERRIDE {
137    test_server_.reset(new EmbeddedTestServer(
138        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)));
139
140    ASSERT_TRUE(test_server_->InitializeAndWaitUntilReady());
141    test_server_->RegisterRequestHandler(
142        base::Bind(&PeopleProviderTest::HandleRequest,
143                   base::Unretained(this)));
144
145    people_provider_.reset(new PeopleProvider(
146        ProfileManager::GetDefaultProfile()));
147
148    people_provider_->SetupForTest(
149        base::Bind(&PeopleProviderTest::OnSearchResultsFetched,
150                   base::Unretained(this)),
151        test_server_->base_url());
152    people_provider_->set_use_throttling(false);
153  }
154
155  virtual void CleanUpOnMainThread() OVERRIDE {
156    EXPECT_TRUE(test_server_->ShutdownAndWaitUntilComplete());
157    test_server_.reset();
158  }
159
160  std::string RunQuery(const std::string& query,
161                       const std::string& mock_server_response) {
162    people_provider_->Start(UTF8ToUTF16(query));
163
164    if (people_provider_->people_search_ && !mock_server_response.empty()) {
165      mock_server_response_ = mock_server_response;
166
167      DCHECK(!run_loop_);
168      run_loop_.reset(new base::RunLoop);
169      run_loop_->Run();
170      run_loop_.reset();
171
172      mock_server_response_.clear();
173    }
174
175    people_provider_->Stop();
176    return GetResults();
177  }
178
179  std::string GetResults() const {
180    std::string results;
181    for (SearchProvider::Results::const_iterator it =
182             people_provider_->results().begin();
183         it != people_provider_->results().end();
184         ++it) {
185      if (!results.empty())
186        results += ',';
187      results += UTF16ToUTF8((*it)->title());
188    }
189    return results;
190  }
191
192  PeopleProvider* people_provider() { return people_provider_.get(); }
193
194 private:
195  scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) {
196    scoped_ptr<BasicHttpResponse> response(new BasicHttpResponse);
197    response->set_code(net::HTTP_OK);
198    response->set_content(mock_server_response_);
199
200    return response.PassAs<HttpResponse>();
201  }
202
203  void OnSearchResultsFetched() {
204    if (run_loop_)
205      run_loop_->Quit();
206  }
207
208  scoped_ptr<EmbeddedTestServer> test_server_;
209  scoped_ptr<base::RunLoop> run_loop_;
210
211  std::string mock_server_response_;
212
213  scoped_ptr<PeopleProvider> people_provider_;
214
215  DISALLOW_COPY_AND_ASSIGN(PeopleProviderTest);
216};
217
218IN_PROC_BROWSER_TEST_F(PeopleProviderTest, Basic) {
219  struct {
220    const char* query;
221    const char* mock_server_response;
222    const char* expected_results_content;
223  } kTestCases[] = {
224    {"first", kOneResult, "first person" },
225    {"person", kThreeValidResults, "first person,second person,third person" },
226  };
227
228  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) {
229    EXPECT_EQ(kTestCases[i].expected_results_content,
230              RunQuery(kTestCases[i].query,
231                       kTestCases[i].mock_server_response))
232        << "Case " << i << ": q=" << kTestCases[i].query;
233  }
234}
235
236IN_PROC_BROWSER_TEST_F(PeopleProviderTest, NoSearchForSensitiveData) {
237  // None of the following input strings should be accepted because they may
238  // contain private data.
239  const char* inputs[] = {
240    // file: scheme is bad.
241    "file://filename",
242    "FILE://filename",
243    // URLs with usernames, ports, queries or refs are bad.
244    "http://username:password@hostname/",
245    "http://www.example.com:1000",
246    "http://foo:1000",
247    "http://hostname/?query=q",
248    "http://hostname/path#ref",
249    // A https URL with path is bad.
250    "https://hostname/path",
251  };
252
253  for (size_t i = 0; i < arraysize(inputs); ++i)
254    EXPECT_EQ("", RunQuery(inputs[i], kOneResult));
255}
256
257IN_PROC_BROWSER_TEST_F(PeopleProviderTest, NoSearchForShortQueries) {
258  EXPECT_EQ("", RunQuery("f", kOneResult));
259  EXPECT_EQ("", RunQuery("fi", kOneResult));
260  EXPECT_EQ("first person", RunQuery("fir", kOneResult));
261}
262
263}  // namespace test
264}  // namespace app_list
265