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