Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(647)

Side by Side Diff: chrome/browser/ui/app_list/search/webstore_provider.cc

Issue 23874015: Implement people search. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 "chrome/browser/ui/app_list/search/webstore_provider.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/search/search.h"
17 #include "chrome/browser/ui/app_list/search/search_webstore_result.h"
18 #include "chrome/browser/ui/app_list/search/webstore_result.h"
19 #include "chrome/browser/ui/app_list/search/webstore_search_fetcher.h"
20 #include "chrome/common/extensions/extension_constants.h"
21 #include "chrome/common/url_constants.h"
22 #include "url/gurl.h"
23
24 namespace app_list {
25
26 namespace {
27
28 const char kKeyResults[] = "results";
29 const char kKeyId[] = "id";
30 const char kKeyLocalizedName[] = "localized_name";
31 const char kKeyIconUrl[] = "icon_url";
32 const size_t kMinimumQueryLength = 3u;
33 const int kWebstoreQueryThrottleIntrevalInMs = 100;
34
35 // Returns true if the launcher should send queries to the web store server.
36 bool UseWebstoreSearch() {
37 const char kFieldTrialName[] = "LauncherUseWebstoreSearch";
38 const char kEnable[] = "Enable";
39 return base::FieldTrialList::FindFullName(kFieldTrialName) == kEnable;
40 }
41
42 // Returns whether or not the user's input string, |query|, might contain any
43 // sensitive information, based purely on its value and not where it came from.
44 bool IsSensitiveInput(const string16& query) {
45 const GURL query_as_url(query);
46 if (!query_as_url.is_valid())
47 return false;
48
49 // The input can be interpreted as a URL. Check to see if it is potentially
50 // sensitive. (Code shamelessly copied from search_provider.cc's
51 // IsQuerySuitableForSuggest function.)
52
53 // First we check the scheme: if this looks like a URL with a scheme that is
54 // file, we shouldn't send it. Sending such things is a waste of time and a
55 // disclosure of potentially private, local data. If the scheme is OK, we
56 // still need to check other cases below.
57 if (LowerCaseEqualsASCII(query_as_url.scheme(), chrome::kFileScheme))
58 return true;
59
60 // Don't send URLs with usernames, queries or refs. Some of these are
61 // private, and the Suggest server is unlikely to have any useful results
62 // for any of them. Also don't send URLs with ports, as we may initially
63 // think that a username + password is a host + port (and we don't want to
64 // send usernames/passwords), and even if the port really is a port, the
65 // server is once again unlikely to have and useful results.
66 if (!query_as_url.username().empty() ||
67 !query_as_url.port().empty() ||
68 !query_as_url.query().empty() ||
69 !query_as_url.ref().empty()) {
70 return true;
71 }
72
73 // Don't send anything for https except the hostname. Hostnames are OK
74 // because they are visible when the TCP connection is established, but the
75 // specific path may reveal private information.
76 if (LowerCaseEqualsASCII(query_as_url.scheme(), content::kHttpsScheme) &&
77 !query_as_url.path().empty() && query_as_url.path() != "/") {
78 return true;
79 }
80
81 return false;
82 }
83
84 } // namespace
85
86 WebstoreProvider::WebstoreProvider(Profile* profile,
87 AppListControllerDelegate* controller)
88 : profile_(profile),
89 controller_(controller),
90 use_throttling_(true) {}
91
92 WebstoreProvider::~WebstoreProvider() {}
93
94 void WebstoreProvider::Start(const base::string16& query) {
95 ClearResults();
96
97 // If |query| contains sensitive data, bail out and do not create the place
98 // holder "search-web-store" result.
99 if (IsSensitiveInput(query)) {
100 query_.clear();
101 return;
102 }
103
104 const std::string query_utf8 = UTF16ToUTF8(query);
105
106 if (query_utf8.size() < kMinimumQueryLength) {
107 query_.clear();
108 return;
109 }
110
111 query_ = query_utf8;
112 const base::DictionaryValue* cached_result = cache_.Get(query_);
113 if (cached_result) {
114 ProcessWebstoreSearchResults(cached_result);
115 if (!webstore_search_fetched_callback_.is_null())
116 webstore_search_fetched_callback_.Run();
117 return;
118 }
119
120 if (UseWebstoreSearch() && chrome::IsSuggestPrefEnabled(profile_)) {
121 if (!webstore_search_) {
122 webstore_search_.reset(new WebstoreSearchFetcher(
123 base::Bind(&WebstoreProvider::OnWebstoreSearchFetched,
124 base::Unretained(this)),
125 profile_->GetRequestContext()));
126 }
127
128 base::TimeDelta interval =
129 base::TimeDelta::FromMilliseconds(kWebstoreQueryThrottleIntrevalInMs);
130 if (!use_throttling_ || base::Time::Now() - last_keytyped_ > interval) {
131 query_throttler_.Stop();
132 StartQuery();
133 } else {
134 query_throttler_.Start(
135 FROM_HERE,
136 interval,
137 base::Bind(&WebstoreProvider::StartQuery, base::Unretained(this)));
138 }
139 last_keytyped_ = base::Time::Now();
140 }
141
142 // Add a placeholder result which when clicked will run the user's query in a
143 // browser. This placeholder is removed when the search results arrive.
144 Add(scoped_ptr<ChromeSearchResult>(
145 new SearchWebstoreResult(profile_, query_utf8)).Pass());
146 }
147
148 void WebstoreProvider::Stop() {
149 if (webstore_search_)
150 webstore_search_->Stop();
151 }
152
153 void WebstoreProvider::StartQuery() {
154 // |query_| can be NULL when the query is scheduled but then canceled.
155 if (!webstore_search_ || query_.empty())
156 return;
157
158 webstore_search_->Start(query_, g_browser_process->GetApplicationLocale());
159 }
160
161 void WebstoreProvider::OnWebstoreSearchFetched(
162 scoped_ptr<base::DictionaryValue> json) {
163 ProcessWebstoreSearchResults(json.get());
164 cache_.Put(query_, json.Pass());
165
166 if (!webstore_search_fetched_callback_.is_null())
167 webstore_search_fetched_callback_.Run();
168 }
169
170 void WebstoreProvider::ProcessWebstoreSearchResults(
171 const base::DictionaryValue* json) {
172 const base::ListValue* result_list = NULL;
173 if (!json ||
174 !json->GetList(kKeyResults, &result_list) ||
175 !result_list ||
176 result_list->empty()) {
177 return;
178 }
179
180 bool first_result = true;
181 for (ListValue::const_iterator it = result_list->begin();
182 it != result_list->end();
183 ++it) {
184 const base::DictionaryValue* dict;
185 if (!(*it)->GetAsDictionary(&dict))
186 continue;
187
188 scoped_ptr<ChromeSearchResult> result(CreateResult(*dict));
189 if (!result)
190 continue;
191
192 if (first_result) {
193 // Clears "search in webstore" place holder results.
194 ClearResults();
195 first_result = false;
196 }
197
198 Add(result.Pass());
199 }
200 }
201
202 scoped_ptr<ChromeSearchResult> WebstoreProvider::CreateResult(
203 const base::DictionaryValue& dict) {
204 scoped_ptr<ChromeSearchResult> result;
205
206 std::string app_id;
207 std::string localized_name;
208 std::string icon_url_string;
209 if (!dict.GetString(kKeyId, &app_id) ||
210 !dict.GetString(kKeyLocalizedName, &localized_name) ||
211 !dict.GetString(kKeyIconUrl, &icon_url_string)) {
212 return result.Pass();
213 }
214
215 GURL icon_url(icon_url_string);
216 if (!icon_url.is_valid())
217 return result.Pass();
218
219 result.reset(new WebstoreResult(
220 profile_, app_id, localized_name, icon_url, controller_));
221 return result.Pass();
222 }
223
224 } // namespace app_list
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698