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