Home | History | Annotate | Download | only in common
      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 
     18 namespace app_list {
     19 
     20 namespace {
     21 
     22 const int kWebserviceQueryThrottleIntrevalInMs = 100;
     23 const size_t kMinimumQueryLength = 3u;
     24 
     25 }  // namespace
     26 
     27 WebserviceSearchProvider::WebserviceSearchProvider(Profile* profile)
     28     : profile_(profile),
     29       cache_(WebserviceCacheFactory::GetForBrowserContext(profile)),
     30       use_throttling_(true) {}
     31 
     32 WebserviceSearchProvider::~WebserviceSearchProvider() {}
     33 
     34 void 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 
     47 bool WebserviceSearchProvider::IsValidQuery(const base::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.
     61 bool WebserviceSearchProvider::IsSensitiveInput(const base::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