OLD | NEW |
| (Empty) |
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/webstore_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 | |
23 using content::BrowserThread; | |
24 using net::test_server::BasicHttpResponse; | |
25 using net::test_server::HttpRequest; | |
26 using net::test_server::HttpResponse; | |
27 using net::test_server::EmbeddedTestServer; | |
28 | |
29 namespace app_list { | |
30 namespace test { | |
31 namespace { | |
32 | |
33 // Mock results. | |
34 const char kOneResult[] = "{" | |
35 "\"search_url\": \"http://host/search\"," | |
36 "\"results\":[" | |
37 "{" | |
38 "\"id\": \"app1_id\"," | |
39 "\"localized_name\": \"app1 name\"," | |
40 "\"icon_url\": \"http://host/icon\"" | |
41 "}" | |
42 "]}"; | |
43 | |
44 const char kThreeResults[] = "{" | |
45 "\"search_url\": \"http://host/search\"," | |
46 "\"results\":[" | |
47 "{" | |
48 "\"id\": \"app1_id\"," | |
49 "\"localized_name\": \"one\"," | |
50 "\"icon_url\": \"http://host/icon\"" | |
51 "}," | |
52 "{" | |
53 "\"id\": \"app2_id\"," | |
54 "\"localized_name\": \"two\"," | |
55 "\"icon_url\": \"http://host/icon\"" | |
56 "}," | |
57 "{" | |
58 "\"id\": \"app3_id\"," | |
59 "\"localized_name\": \"three\"," | |
60 "\"icon_url\": \"http://host/icon\"" | |
61 "}" | |
62 "]}"; | |
63 | |
64 } // namespace | |
65 | |
66 class WebstoreProviderTest : public InProcessBrowserTest { | |
67 public: | |
68 WebstoreProviderTest() {} | |
69 virtual ~WebstoreProviderTest() {} | |
70 | |
71 // InProcessBrowserTest overrides: | |
72 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | |
73 command_line->AppendSwitchASCII(switches::kForceFieldTrials, | |
74 "LauncherUseWebstoreSearch/Enable/"); | |
75 } | |
76 | |
77 virtual void SetUpOnMainThread() OVERRIDE { | |
78 test_server_.reset(new EmbeddedTestServer( | |
79 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))); | |
80 | |
81 ASSERT_TRUE(test_server_->InitializeAndWaitUntilReady()); | |
82 test_server_->RegisterRequestHandler( | |
83 base::Bind(&WebstoreProviderTest::HandleRequest, | |
84 base::Unretained(this))); | |
85 CommandLine::ForCurrentProcess()->AppendSwitchASCII( | |
86 switches::kAppsGalleryURL, test_server_->base_url().spec()); | |
87 | |
88 webstore_provider_.reset(new WebstoreProvider( | |
89 ProfileManager::GetDefaultProfile(), NULL)); | |
90 webstore_provider_->set_webstore_search_fetched_callback( | |
91 base::Bind(&WebstoreProviderTest::OnSearchResultsFetched, | |
92 base::Unretained(this))); | |
93 // TODO(mukai): add test cases for throttling. | |
94 webstore_provider_->set_use_throttling(false); | |
95 } | |
96 | |
97 virtual void CleanUpOnMainThread() OVERRIDE { | |
98 EXPECT_TRUE(test_server_->ShutdownAndWaitUntilComplete()); | |
99 test_server_.reset(); | |
100 } | |
101 | |
102 std::string RunQuery(const std::string& query, | |
103 const std::string& mock_server_response) { | |
104 webstore_provider_->Start(UTF8ToUTF16(query)); | |
105 | |
106 if (webstore_provider_->webstore_search_ && !mock_server_response.empty()) { | |
107 mock_server_response_ = mock_server_response; | |
108 | |
109 DCHECK(!run_loop_); | |
110 run_loop_.reset(new base::RunLoop); | |
111 run_loop_->Run(); | |
112 run_loop_.reset(); | |
113 | |
114 mock_server_response_.clear(); | |
115 } | |
116 | |
117 webstore_provider_->Stop(); | |
118 return GetResults(); | |
119 } | |
120 | |
121 std::string GetResults() const { | |
122 std::string results; | |
123 for (SearchProvider::Results::const_iterator it = | |
124 webstore_provider_->results().begin(); | |
125 it != webstore_provider_->results().end(); | |
126 ++it) { | |
127 if (!results.empty()) | |
128 results += ','; | |
129 results += UTF16ToUTF8((*it)->title()); | |
130 } | |
131 return results; | |
132 } | |
133 | |
134 WebstoreProvider* webstore_provider() { return webstore_provider_.get(); } | |
135 | |
136 private: | |
137 scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { | |
138 scoped_ptr<BasicHttpResponse> response(new BasicHttpResponse); | |
139 | |
140 if (request.relative_url.find("/jsonsearch?") != std::string::npos) { | |
141 if (mock_server_response_ == "404") { | |
142 response->set_code(net::HTTP_NOT_FOUND); | |
143 } else if (mock_server_response_ == "500") { | |
144 response->set_code(net::HTTP_INTERNAL_SERVER_ERROR); | |
145 } else { | |
146 response->set_code(net::HTTP_OK); | |
147 response->set_content(mock_server_response_); | |
148 } | |
149 } | |
150 | |
151 return response.PassAs<HttpResponse>(); | |
152 } | |
153 | |
154 void OnSearchResultsFetched() { | |
155 if (run_loop_) | |
156 run_loop_->Quit(); | |
157 } | |
158 | |
159 scoped_ptr<EmbeddedTestServer> test_server_; | |
160 scoped_ptr<base::RunLoop> run_loop_; | |
161 | |
162 std::string mock_server_response_; | |
163 | |
164 scoped_ptr<WebstoreProvider> webstore_provider_; | |
165 | |
166 DISALLOW_COPY_AND_ASSIGN(WebstoreProviderTest); | |
167 }; | |
168 | |
169 // Flaky on Windows: http://crbug.com/246136. | |
170 #if defined(OS_WIN) | |
171 #define MAYBE_Basic DISABLED_Basic | |
172 #else | |
173 #define MAYBE_Basic Basic | |
174 #endif | |
175 IN_PROC_BROWSER_TEST_F(WebstoreProviderTest, MAYBE_Basic) { | |
176 struct { | |
177 const char* query; | |
178 const char* mock_server_response; | |
179 const char* expected_results_content; | |
180 } kTestCases[] = { | |
181 // "Search in web store" result with query text itself is used for | |
182 // synchronous placeholder, bad server response etc. | |
183 {"synchronous", "", "synchronous" }, | |
184 {"404", "404", "404" }, | |
185 {"500", "500", "500" }, | |
186 {"bad json", "invalid json", "bad json" }, | |
187 // Good results. | |
188 {"1 result", kOneResult, "app1 name" }, | |
189 {"3 result", kThreeResults, "one,two,three" }, | |
190 }; | |
191 | |
192 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | |
193 EXPECT_EQ(kTestCases[i].expected_results_content, | |
194 RunQuery(kTestCases[i].query, | |
195 kTestCases[i].mock_server_response)) | |
196 << "Case " << i << ": q=" << kTestCases[i].query; | |
197 } | |
198 } | |
199 | |
200 IN_PROC_BROWSER_TEST_F(WebstoreProviderTest, NoSearchForSensitiveData) { | |
201 // None of the following input strings should be accepted because they may | |
202 // contain private data. | |
203 const char* inputs[] = { | |
204 // file: scheme is bad. | |
205 "file://filename", | |
206 "FILE://filename", | |
207 // URLs with usernames, ports, queries or refs are bad. | |
208 "http://username:password@hostname/", | |
209 "http://www.example.com:1000", | |
210 "http://foo:1000", | |
211 "http://hostname/?query=q", | |
212 "http://hostname/path#ref", | |
213 // A https URL with path is bad. | |
214 "https://hostname/path", | |
215 }; | |
216 | |
217 for (size_t i = 0; i < arraysize(inputs); ++i) | |
218 EXPECT_EQ("", RunQuery(inputs[i], kOneResult)); | |
219 } | |
220 | |
221 IN_PROC_BROWSER_TEST_F(WebstoreProviderTest, NoSearchForShortQueries) { | |
222 EXPECT_EQ("", RunQuery("a", kOneResult)); | |
223 EXPECT_EQ("", RunQuery("ab", kOneResult)); | |
224 EXPECT_EQ("app1 name", RunQuery("abc", kOneResult)); | |
225 } | |
226 | |
227 IN_PROC_BROWSER_TEST_F(WebstoreProviderTest, SearchCache) { | |
228 EXPECT_EQ("app1 name", RunQuery("foo", kOneResult)); | |
229 | |
230 // No result is provided but the provider gets the result from the cache. | |
231 EXPECT_EQ("app1 name", RunQuery("foo", "")); | |
232 } | |
233 | |
234 } // namespace test | |
235 } // namespace app_list | |
OLD | NEW |