people_provider_browsertest.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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 "\"metadata\" : {" 40 "\"ownerId\": \"1\"" 41 "}," 42 "\"names\" : [{" 43 "\"displayName\": \"first person\"" 44 "}]," 45 "\"emails\" : [{" 46 "\"value\": \"first@person.com\"" 47 "}]," 48 "\"images\" : [{" 49 "\"url\": \"http://host/icon\"" 50 "}]," 51 "\"sortKeys\" : {" 52 "\"interactionRank\": \"0.98\"" 53 "}" 54 "}" 55 "}" 56 "]}"; 57 58const char kThreeValidResults[] = "{" 59 "\"items\":[" 60 "{" 61 "\"person\" : {" 62 "\"id\": \"1\"," 63 "\"metadata\" : {" 64 "\"ownerId\": \"1\"" 65 "}," 66 "\"names\" : [{" 67 "\"displayName\": \"first person\"" 68 "}]," 69 "\"emails\" : [{" 70 "\"value\": \"first@person.com\"" 71 "}]," 72 "\"images\" : [{" 73 "\"url\": \"http://host/icon\"" 74 "}]," 75 "\"sortKeys\" : {" 76 "\"interactionRank\": \"0.98\"" 77 "}" 78 "}" 79 "}," 80 "{" 81 "\"person\" : {" 82 "\"id\": \"2\"," 83 "\"metadata\" : {" 84 "\"ownerId\": \"37\"" 85 "}," 86 "\"names\" : [{" 87 "\"displayName\": \"second person\"" 88 "}]," 89 "\"emails\" : [{" 90 "\"value\": \"second@person.com\"" 91 "}]," 92 "\"images\" : [{" 93 "\"url\": \"http://host/icon\"" 94 "}]," 95 "\"sortKeys\" : {" 96 "\"interactionRank\": \"0.84\"" 97 "}" 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 SetUpCommandLine(CommandLine* command_line) OVERRIDE { 169 command_line->AppendSwitch(switches::kEnablePeopleSearch); 170 } 171 172 virtual void SetUpOnMainThread() OVERRIDE { 173 test_server_.reset(new EmbeddedTestServer); 174 175 ASSERT_TRUE(test_server_->InitializeAndWaitUntilReady()); 176 test_server_->RegisterRequestHandler( 177 base::Bind(&PeopleProviderTest::HandleRequest, 178 base::Unretained(this))); 179 180 people_provider_.reset(new PeopleProvider( 181 ProfileManager::GetDefaultProfile())); 182 183 people_provider_->SetupForTest( 184 base::Bind(&PeopleProviderTest::OnSearchResultsFetched, 185 base::Unretained(this)), 186 test_server_->base_url()); 187 people_provider_->set_use_throttling(false); 188 } 189 190 virtual void CleanUpOnMainThread() OVERRIDE { 191 EXPECT_TRUE(test_server_->ShutdownAndWaitUntilComplete()); 192 test_server_.reset(); 193 } 194 195 std::string RunQuery(const std::string& query, 196 const std::string& mock_server_response) { 197 people_provider_->Start(UTF8ToUTF16(query)); 198 199 if (people_provider_->people_search_ && !mock_server_response.empty()) { 200 mock_server_response_ = mock_server_response; 201 202 DCHECK(!run_loop_); 203 run_loop_.reset(new base::RunLoop); 204 run_loop_->Run(); 205 run_loop_.reset(); 206 207 mock_server_response_.clear(); 208 } 209 210 people_provider_->Stop(); 211 return GetResults(); 212 } 213 214 std::string GetResults() const { 215 std::string results; 216 for (SearchProvider::Results::const_iterator it = 217 people_provider_->results().begin(); 218 it != people_provider_->results().end(); 219 ++it) { 220 if (!results.empty()) 221 results += ','; 222 results += UTF16ToUTF8((*it)->title()); 223 } 224 return results; 225 } 226 227 PeopleProvider* people_provider() { return people_provider_.get(); } 228 229 private: 230 scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { 231 scoped_ptr<BasicHttpResponse> response(new BasicHttpResponse); 232 response->set_code(net::HTTP_OK); 233 response->set_content(mock_server_response_); 234 235 return response.PassAs<HttpResponse>(); 236 } 237 238 void OnSearchResultsFetched() { 239 if (run_loop_) 240 run_loop_->Quit(); 241 } 242 243 scoped_ptr<EmbeddedTestServer> test_server_; 244 scoped_ptr<base::RunLoop> run_loop_; 245 246 std::string mock_server_response_; 247 248 scoped_ptr<PeopleProvider> people_provider_; 249 250 DISALLOW_COPY_AND_ASSIGN(PeopleProviderTest); 251}; 252 253IN_PROC_BROWSER_TEST_F(PeopleProviderTest, Basic) { 254 struct { 255 const char* query; 256 const char* mock_server_response; 257 const char* expected_results_content; 258 } kTestCases[] = { 259 {"first", kOneResult, "first person" }, 260 {"person", kThreeValidResults, "first person,second person,third person" }, 261 }; 262 263 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { 264 EXPECT_EQ(kTestCases[i].expected_results_content, 265 RunQuery(kTestCases[i].query, 266 kTestCases[i].mock_server_response)) 267 << "Case " << i << ": q=" << kTestCases[i].query; 268 } 269} 270 271IN_PROC_BROWSER_TEST_F(PeopleProviderTest, NoSearchForSensitiveData) { 272 // None of the following input strings should be accepted because they may 273 // contain private data. 274 const char* inputs[] = { 275 // file: scheme is bad. 276 "file://filename", 277 "FILE://filename", 278 // URLs with usernames, ports, queries or refs are bad. 279 "http://username:password@hostname/", 280 "http://www.example.com:1000", 281 "http://foo:1000", 282 "http://hostname/?query=q", 283 "http://hostname/path#ref", 284 // A https URL with path is bad. 285 "https://hostname/path", 286 }; 287 288 for (size_t i = 0; i < arraysize(inputs); ++i) 289 EXPECT_EQ("", RunQuery(inputs[i], kOneResult)); 290} 291 292IN_PROC_BROWSER_TEST_F(PeopleProviderTest, NoSearchForShortQueries) { 293 EXPECT_EQ("", RunQuery("f", kOneResult)); 294 EXPECT_EQ("", RunQuery("fi", kOneResult)); 295 EXPECT_EQ("first person", RunQuery("fir", kOneResult)); 296} 297 298} // namespace test 299} // namespace app_list 300