webservice_search_provider.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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/common/webservice_search_provider.h"
6
7#include <string>
8
9#include "base/callback.h"
10#include "base/strings/string_util.h"
11#include "chrome/browser/profiles/profile.h"
12#include "chrome/browser/search/search.h"
13#include "chrome/browser/ui/app_list/search/common/webservice_cache.h"
14#include "chrome/browser/ui/app_list/search/common/webservice_cache_factory.h"
15#include "chrome/common/url_constants.h"
16#include "url/gurl.h"
17
18namespace app_list {
19
20namespace {
21
22const int kWebserviceQueryThrottleIntrevalInMs = 100;
23const size_t kMinimumQueryLength = 3u;
24
25}  // namespace
26
27WebserviceSearchProvider::WebserviceSearchProvider(Profile* profile)
28    : profile_(profile),
29      cache_(WebserviceCacheFactory::GetForBrowserContext(profile)),
30      use_throttling_(true) {}
31
32WebserviceSearchProvider::~WebserviceSearchProvider() {}
33
34void WebserviceSearchProvider::StartThrottledQuery(
35    const base::Closure& start_query) {
36  base::TimeDelta interval =
37      base::TimeDelta::FromMilliseconds(kWebserviceQueryThrottleIntrevalInMs);
38  if (!use_throttling_ || base::Time::Now() - last_keytyped_ > interval) {
39    query_throttler_.Stop();
40    start_query.Run();
41  } else {
42    query_throttler_.Start(FROM_HERE, interval, start_query);
43  }
44  last_keytyped_ = base::Time::Now();
45}
46
47bool WebserviceSearchProvider::IsValidQuery(const string16& query) {
48  // If |query| contains sensitive data, bail out and do not create the place
49  // holder "search-web-store" result.
50  if (IsSensitiveInput(query) ||
51      (query.size() < kMinimumQueryLength) ||
52      !chrome::IsSuggestPrefEnabled(profile_)) {
53    return false;
54  }
55
56  return true;
57}
58
59// Returns whether or not the user's input string, |query|, might contain any
60// sensitive information, based purely on its value and not where it came from.
61bool WebserviceSearchProvider::IsSensitiveInput(const string16& query) {
62  const GURL query_as_url(query);
63  if (!query_as_url.is_valid())
64    return false;
65
66  // The input can be interpreted as a URL. Check to see if it is potentially
67  // sensitive. (Code shamelessly copied from search_provider.cc's
68  // IsQuerySuitableForSuggest function.)
69
70  // First we check the scheme: if this looks like a URL with a scheme that is
71  // file, we shouldn't send it. Sending such things is a waste of time and a
72  // disclosure of potentially private, local data. If the scheme is OK, we
73  // still need to check other cases below.
74  if (LowerCaseEqualsASCII(query_as_url.scheme(), chrome::kFileScheme))
75    return true;
76
77  // Don't send URLs with usernames, queries or refs. Some of these are
78  // private, and the Suggest server is unlikely to have any useful results
79  // for any of them. Also don't send URLs with ports, as we may initially
80  // think that a username + password is a host + port (and we don't want to
81  // send usernames/passwords), and even if the port really is a port, the
82  // server is once again unlikely to have and useful results.
83  if (!query_as_url.username().empty() ||
84      !query_as_url.port().empty() ||
85      !query_as_url.query().empty() ||
86      !query_as_url.ref().empty()) {
87    return true;
88  }
89
90  // Don't send anything for https except the hostname. Hostnames are OK
91  // because they are visible when the TCP connection is established, but the
92  // specific path may reveal private information.
93  if (LowerCaseEqualsASCII(query_as_url.scheme(), content::kHttpsScheme) &&
94      !query_as_url.path().empty() && query_as_url.path() != "/") {
95    return true;
96  }
97
98  return false;
99}
100
101}  // namespace app_list
102