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