12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string> 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h" 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/command_line.h" 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/run_loop.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/app_list/search/chrome_search_result.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/app_list/search/people/people_provider.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_switches.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/test/embedded_test_server/http_request.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/test/embedded_test_server/http_response.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::BrowserThread; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using net::test_server::BasicHttpResponse; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using net::test_server::HttpRequest; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using net::test_server::HttpResponse; 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using net::test_server::EmbeddedTestServer; 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace app_list { 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace test { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Mock results. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kOneResult[] = "{" 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "\"items\":[" 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "\"person\" : {" 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "\"id\": \"1\"," 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"metadata\" : {" 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"ownerId\": \"1\"" 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}," 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"names\" : [{" 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"displayName\": \"first person\"" 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}]," 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"emails\" : [{" 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"value\": \"first@person.com\"" 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}]," 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"images\" : [{" 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"url\": \"http://host/icon\"" 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}]," 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"sortKeys\" : {" 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "\"interactionRank\": \"0.98\"" 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}" 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "}" 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "}" 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "]}"; 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kThreeValidResults[] = "{" 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"items\":[" 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "{" 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"person\" : {" 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"id\": \"1\"," 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"metadata\" : {" 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "\"ownerId\": \"1\"" 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}," 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"names\" : [{" 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"displayName\": \"first person\"" 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}]," 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"emails\" : [{" 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"value\": \"first@person.com\"" 71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) "}]," 72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) "\"images\" : [{" 73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) "\"url\": \"http://host/icon\"" 74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) "}]," 75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) "\"sortKeys\" : {" 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"interactionRank\": \"0.98\"" 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}" 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}" 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}," 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "{" 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "\"person\" : {" 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "\"id\": \"2\"," 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "\"metadata\" : {" 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"ownerId\": \"37\"" 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}," 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"names\" : [{" 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"displayName\": \"second person\"" 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}]," 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"emails\" : [{" 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"value\": \"second@person.com\"" 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}]," 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"images\" : [{" 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"url\": \"http://host/icon\"" 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "}]," 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) "\"sortKeys\" : {" 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "\"interactionRank\": \"0.84\"" 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "}" 98 "}" 99 "}," 100 "{" 101 "\"person\" : {" 102 "\"id\": \"3\"," 103 "\"metadata\" : {" 104 "\"ownerId\": \"3\"" 105 "}," 106 "\"names\" : [{" 107 "\"displayName\": \"third person\"" 108 "}]," 109 "\"emails\" : [{" 110 "\"value\": \"third@person.com\"" 111 "}]," 112 "\"images\" : [{" 113 "\"url\": \"http://host/icon\"" 114 "}]," 115 "\"sortKeys\" : {" 116 "\"interactionRank\": \"0.67\"" 117 "}" 118 "}" 119 "}," 120 "{" 121 "\"person\" : {" 122 "\"id\": \"4\"," 123 "\"metadata\" : {" 124 "\"ownerId\": \"4\"" 125 "}," 126 "\"names\" : [{" 127 "\"displayName\": \"fourth person\"" 128 "}]," 129 "\"emails\" : [{" 130 "\"value\": \"fourth@person.com\"" 131 "}]," 132 "\"images\" : [{" 133 "\"url\": \"http://host/icon\"" 134 "}]," 135 "\"sortKeys\" : {" 136 "\"interactionRank\": \"0.0\"" 137 "}" 138 "}" 139 "}," 140 "{" 141 "\"person\" : {" 142 "\"id\": \"5\"," 143 "\"metadata\" : {" 144 "\"ownerId\": \"5\"" 145 "}," 146 "\"names\" : [{" 147 "\"displayName\": \"fifth person\"" 148 "}]," 149 "\"emails\" : [{" 150 "\"value\": \"fifth@person.com\"" 151 "}]," 152 // Images field is missing on purpose. 153 "\"sortKeys\" : {" 154 "\"interactionRank\": \"0.98\"" 155 "}" 156 "}" 157 "}" 158 "]}"; 159 160} // namespace 161 162class PeopleProviderTest : public InProcessBrowserTest { 163 public: 164 PeopleProviderTest() {} 165 virtual ~PeopleProviderTest() {} 166 167 // InProcessBrowserTest overrides: 168 virtual void SetUpOnMainThread() OVERRIDE { 169 test_server_.reset(new EmbeddedTestServer); 170 171 ASSERT_TRUE(test_server_->InitializeAndWaitUntilReady()); 172 test_server_->RegisterRequestHandler( 173 base::Bind(&PeopleProviderTest::HandleRequest, 174 base::Unretained(this))); 175 176 people_provider_.reset(new PeopleProvider( 177 ProfileManager::GetActiveUserProfile())); 178 179 people_provider_->SetupForTest( 180 base::Bind(&PeopleProviderTest::OnSearchResultsFetched, 181 base::Unretained(this)), 182 test_server_->base_url()); 183 people_provider_->set_use_throttling(false); 184 } 185 186 virtual void TearDownOnMainThread() OVERRIDE { 187 EXPECT_TRUE(test_server_->ShutdownAndWaitUntilComplete()); 188 test_server_.reset(); 189 } 190 191 std::string RunQuery(const std::string& query, 192 const std::string& mock_server_response) { 193 people_provider_->Start(base::UTF8ToUTF16(query)); 194 195 if (people_provider_->people_search_ && !mock_server_response.empty()) { 196 mock_server_response_ = mock_server_response; 197 198 DCHECK(!run_loop_); 199 run_loop_.reset(new base::RunLoop); 200 run_loop_->Run(); 201 run_loop_.reset(); 202 203 mock_server_response_.clear(); 204 } 205 206 people_provider_->Stop(); 207 return GetResults(); 208 } 209 210 std::string GetResults() const { 211 std::string results; 212 for (SearchProvider::Results::const_iterator it = 213 people_provider_->results().begin(); 214 it != people_provider_->results().end(); 215 ++it) { 216 if (!results.empty()) 217 results += ','; 218 results += base::UTF16ToUTF8((*it)->title()); 219 } 220 return results; 221 } 222 223 PeopleProvider* people_provider() { return people_provider_.get(); } 224 225 private: 226 scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { 227 scoped_ptr<BasicHttpResponse> response(new BasicHttpResponse); 228 response->set_code(net::HTTP_OK); 229 response->set_content(mock_server_response_); 230 231 return response.PassAs<HttpResponse>(); 232 } 233 234 void OnSearchResultsFetched() { 235 if (run_loop_) 236 run_loop_->Quit(); 237 } 238 239 scoped_ptr<EmbeddedTestServer> test_server_; 240 scoped_ptr<base::RunLoop> run_loop_; 241 242 std::string mock_server_response_; 243 244 scoped_ptr<PeopleProvider> people_provider_; 245 246 DISALLOW_COPY_AND_ASSIGN(PeopleProviderTest); 247}; 248 249IN_PROC_BROWSER_TEST_F(PeopleProviderTest, Basic) { 250 struct { 251 const char* query; 252 const char* mock_server_response; 253 const char* expected_results_content; 254 } kTestCases[] = { 255 {"first", kOneResult, "first person" }, 256 {"person", kThreeValidResults, "first person,second person,third person" }, 257 }; 258 259 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { 260 EXPECT_EQ(kTestCases[i].expected_results_content, 261 RunQuery(kTestCases[i].query, 262 kTestCases[i].mock_server_response)) 263 << "Case " << i << ": q=" << kTestCases[i].query; 264 } 265} 266 267IN_PROC_BROWSER_TEST_F(PeopleProviderTest, NoSearchForSensitiveData) { 268 // None of the following input strings should be accepted because they may 269 // contain private data. 270 const char* inputs[] = { 271 // file: scheme is bad. 272 "file://filename", 273 "FILE://filename", 274 // URLs with usernames, ports, queries or refs are bad. 275 "http://username:password@hostname/", 276 "http://www.example.com:1000", 277 "http://foo:1000", 278 "http://hostname/?query=q", 279 "http://hostname/path#ref", 280 // A https URL with path is bad. 281 "https://hostname/path", 282 }; 283 284 for (size_t i = 0; i < arraysize(inputs); ++i) 285 EXPECT_EQ("", RunQuery(inputs[i], kOneResult)); 286} 287 288IN_PROC_BROWSER_TEST_F(PeopleProviderTest, NoSearchForShortQueries) { 289 EXPECT_EQ("", RunQuery("f", kOneResult)); 290 EXPECT_EQ("", RunQuery("fi", kOneResult)); 291 EXPECT_EQ("first person", RunQuery("fir", kOneResult)); 292} 293 294} // namespace test 295} // namespace app_list 296