Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / android / popular_sites.cc
blob7bacd4c270a99847b7ca6057a9bfb9233749aee4
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.
5 #include "chrome/browser/android/popular_sites.h"
7 #include "base/bind.h"
8 #include "base/files/file_path.h"
9 #include "base/files/file_util.h"
10 #include "base/json/json_reader.h"
11 #include "base/path_service.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/task_runner_util.h"
15 #include "base/values.h"
16 #include "chrome/browser/net/file_downloader.h"
17 #include "chrome/browser/search_engines/template_url_service_factory.h"
18 #include "chrome/common/chrome_paths.h"
19 #include "components/google/core/browser/google_util.h"
20 #include "components/search_engines/search_engine_type.h"
21 #include "components/search_engines/template_url_prepopulate_data.h"
22 #include "components/search_engines/template_url_service.h"
23 #include "content/public/browser/browser_thread.h"
25 using content::BrowserThread;
27 namespace {
29 const char kPopularSitesURLFormat[] = "https://www.gstatic.com/chrome/ntp/%s";
30 const char kPopularSitesFilenameFormat[] = "suggested_sites_%s_2.json";
31 const char kPopularSitesDefaultCountryCode[] = "DEFAULT";
34 // Find out the country code of the user by using the Google country code if
35 // Google is the default search engine set. Fallback to a default if we can't
36 // make an educated guess.
37 std::string GetCountryCode(Profile* profile) {
38 DCHECK(profile);
40 const TemplateURLService* template_url_service =
41 TemplateURLServiceFactory::GetForProfile(profile);
42 DCHECK(template_url_service);
44 const TemplateURL* default_provider =
45 template_url_service->GetDefaultSearchProvider();
46 // It's possible to not have a default provider in the case that the default
47 // search engine is defined by policy.
48 if (!default_provider)
49 return kPopularSitesDefaultCountryCode;
51 bool is_google_search_engine = TemplateURLPrepopulateData::GetEngineType(
52 *default_provider, template_url_service->search_terms_data()) ==
53 SearchEngineType::SEARCH_ENGINE_GOOGLE;
55 if (!is_google_search_engine)
56 return kPopularSitesDefaultCountryCode;
58 GURL search_url = default_provider->GenerateSearchURL(
59 template_url_service->search_terms_data());
61 std::string country_code =
62 base::ToUpperASCII(google_util::GetGoogleCountryCode(search_url));
64 return country_code;
67 std::string GetPopularSitesFilename(Profile* profile,
68 const std::string& filename) {
69 if (!filename.empty())
70 return filename;
72 return base::StringPrintf(kPopularSitesFilenameFormat,
73 GetCountryCode(profile).c_str());
76 base::FilePath GetPopularSitesPath(Profile* profile,
77 const std::string& filename) {
78 base::FilePath dir;
79 PathService::Get(chrome::DIR_USER_DATA, &dir);
80 return dir.AppendASCII(GetPopularSitesFilename(profile, filename));
83 GURL GetPopularSitesURL(Profile* profile, const std::string& filename) {
84 return GURL(base::StringPrintf(kPopularSitesURLFormat,
85 GetPopularSitesFilename(profile, filename).c_str()));
88 scoped_ptr<std::vector<PopularSites::Site>> ReadAndParseJsonFile(
89 const base::FilePath& path) {
90 std::string json;
91 if (!base::ReadFileToString(path, &json)) {
92 DLOG(WARNING) << "Failed reading file";
93 return nullptr;
96 scoped_ptr<base::Value> value =
97 base::JSONReader::Read(json, base::JSON_ALLOW_TRAILING_COMMAS);
98 base::ListValue* list;
99 if (!value || !value->GetAsList(&list)) {
100 DLOG(WARNING) << "Failed parsing json";
101 return nullptr;
104 scoped_ptr<std::vector<PopularSites::Site>> sites(
105 new std::vector<PopularSites::Site>);
106 for (size_t i = 0; i < list->GetSize(); i++) {
107 base::DictionaryValue* item;
108 if (!list->GetDictionary(i, &item))
109 continue;
110 base::string16 title;
111 std::string url;
112 if (!item->GetString("title", &title) || !item->GetString("url", &url))
113 continue;
114 std::string favicon_url;
115 item->GetString("favicon_url", &favicon_url);
116 std::string thumbnail_url;
117 item->GetString("thumbnail_url", &thumbnail_url);
119 sites->push_back(PopularSites::Site(title, GURL(url), GURL(favicon_url),
120 GURL(thumbnail_url)));
123 return sites.Pass();
126 } // namespace
128 PopularSites::Site::Site(const base::string16& title,
129 const GURL& url,
130 const GURL& favicon_url,
131 const GURL& thumbnail_url)
132 : title(title),
133 url(url),
134 favicon_url(favicon_url),
135 thumbnail_url(thumbnail_url) {}
137 PopularSites::Site::~Site() {}
139 PopularSites::PopularSites(Profile* profile,
140 const std::string& filename,
141 net::URLRequestContextGetter* request_context,
142 const FinishedCallback& callback)
143 : callback_(callback), weak_ptr_factory_(this) {
144 base::FilePath path = GetPopularSitesPath(profile, filename);
145 downloader_.reset(new FileDownloader(
146 GetPopularSitesURL(profile, filename), path, request_context,
147 base::Bind(&PopularSites::OnDownloadDone, base::Unretained(this), path)));
150 PopularSites::~PopularSites() {}
152 void PopularSites::OnDownloadDone(const base::FilePath& path, bool success) {
153 if (success) {
154 base::PostTaskAndReplyWithResult(
155 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
156 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN).get(),
157 FROM_HERE,
158 base::Bind(&ReadAndParseJsonFile, path),
159 base::Bind(&PopularSites::OnJsonParsed,
160 weak_ptr_factory_.GetWeakPtr()));
161 } else {
162 DLOG(WARNING) << "Download failed";
163 callback_.Run(false);
166 downloader_.reset();
169 void PopularSites::OnJsonParsed(scoped_ptr<std::vector<Site>> sites) {
170 if (sites)
171 sites_.swap(*sites);
172 else
173 sites_.clear();
174 callback_.Run(!!sites);