web_resource_service.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/web_resource/web_resource_service.h" 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h" 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chrome_thread.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/profile.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/net/url_fetcher.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/load_flags.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_status.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst wchar_t* WebResourceService::kCurrentTipPrefName = L"current_tip"; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst wchar_t* WebResourceService::kTipCachePrefName = L"tips"; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebResourceService::WebResourceFetcher 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : public URLFetcher::Delegate { 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit WebResourceFetcher(WebResourceService* web_resource_service) : 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_factory_(this)), 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_(web_resource_service) { 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delay initial load of resource data into cache so as not to interfere 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with startup time. 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartAfterDelay(int delay_ms) { 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fetcher_factory_.NewRunnableMethod(&WebResourceFetcher::StartFetch), 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay_ms); 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Initializes the fetching of data from the resource server. Data 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // load calls OnURLFetchComplete. 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartFetch() { 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First, put our next cache load on the MessageLoop. 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fetcher_factory_.NewRunnableMethod(&WebResourceFetcher::StartFetch), 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCacheUpdateDelay); 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we are still fetching data, exit. 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (web_resource_service_->in_fetch_) 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->in_fetch_ = true; 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_.reset(new URLFetcher(GURL( 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->web_resource_server_), 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLFetcher::GET, this)); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do not let url fetcher affect existing state in profile (by setting 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cookies, for example. 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_->set_load_flags(net::LOAD_DISABLE_CACHE | 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::LOAD_DO_NOT_SAVE_COOKIES); 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_->set_request_context(Profile::GetDefaultRequestContext()); 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_->Start(); 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // From URLFetcher::Delegate. 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnURLFetchComplete(const URLFetcher* source, 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const URLRequestStatus& status, 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int response_code, 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ResponseCookies& cookies, 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& data) { 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete the URLFetcher when this function exits. 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<URLFetcher> clean_up_fetcher(url_fetcher_.release()); 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't parse data if attempt to download was unsuccessful. 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Stop loading new web resource data, and silently exit. 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!status.is_success() || (response_code != 200)) 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->UpdateResourceCache(data); 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // So that we can delay our start so as not to affect start-up time; also, 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so that we can schedule future cache updates. 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedRunnableMethodFactory<WebResourceFetcher> fetcher_factory_; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tool that fetches the url data from the server. 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<URLFetcher> url_fetcher_; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Our owner and creator. 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<WebResourceService> web_resource_service_; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class coordinates a web resource unpack and parse task which is run in 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a separate process. Results are sent back to this class and routed to 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the WebResourceService. 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebResourceService::UnpackerClient 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : public UtilityProcessHost::Client { 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UnpackerClient(WebResourceService* web_resource_service, 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& json_data) 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : web_resource_service_(web_resource_service), 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch json_data_(json_data), got_response_(false) { 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Start() { 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // balanced in Cleanup. 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we don't have a resource_dispatcher_host_, assume we're in 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a test and run the unpacker directly in-process. 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_utility_process = 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->resource_dispatcher_host_ != NULL && 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (use_utility_process) { 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::ID thread_id; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(ChromeThread::GetCurrentThreadIdentifier(&thread_id)); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::PostTask( 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::IO, FROM_HERE, 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &UnpackerClient::StartProcessOnIOThread, 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->resource_dispatcher_host_, 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thread_id)); 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebResourceUnpacker unpacker(json_data_); 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (unpacker.Run()) { 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnUnpackWebResourceSucceeded(*unpacker.parsed_json()); 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnUnpackWebResourceFailed(unpacker.error_message()); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~UnpackerClient() {} 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // UtilityProcessHost::Client 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnProcessCrashed() { 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (got_response_) 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnUnpackWebResourceFailed( 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Chrome crashed while trying to retrieve web resources."); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnUnpackWebResourceSucceeded( 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& parsed_json) { 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->OnWebResourceUnpacked(parsed_json); 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Cleanup(); 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnUnpackWebResourceFailed(const std::string& error_message) { 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->EndFetch(); 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Cleanup(); 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Release reference and set got_response_. 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Cleanup() { 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (got_response_) 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch got_response_ = true; 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartProcessOnIOThread(ResourceDispatcherHost* rdh, 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChromeThread::ID thread_id) { 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UtilityProcessHost* host = new UtilityProcessHost(rdh, this, thread_id); 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(mrc): get proper file path when we start using web resources 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that need to be unpacked. 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch host->StartWebResourceUnpacker(json_data_); 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<WebResourceService> web_resource_service_; 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Holds raw JSON string. 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& json_data_; 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // True if we got a response from the utility process and have cleaned up 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // already. 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool got_response_; 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(mirandac): replace these servers tomorrow! 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* WebResourceService::kDefaultResourceServer = 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX) 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "https://clients2.google.com/tools/service/npredir?r=chrometips_mac&hl="; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_LINUX) 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "https://clients2.google.com/tools/service/npredir?r=chrometips_linux&hl="; 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "https://clients2.google.com/tools/service/npredir?r=chrometips_win&hl="; 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* WebResourceService::kResourceDirectoryName = 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Resources"; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebResourceService::WebResourceService(Profile* profile) 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : prefs_(profile->GetPrefs()), 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_dir_(profile->GetPath().AppendASCII(kResourceDirectoryName)), 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_fetch_(false) { 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Init(); 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebResourceService::~WebResourceService() { } 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::Init() { 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host(); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_fetcher_ = new WebResourceFetcher(this); 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_->RegisterStringPref(prefs::kNTPTipsCacheUpdate, "0"); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string locale = g_browser_process->GetApplicationLocale(); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (prefs_->HasPrefPath(prefs::kNTPTipsServer)) { 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_server_ = prefs_->GetString(prefs::kNTPTipsServer); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we are in the correct locale, initialization is done. 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (EndsWith(web_resource_server_, locale, false)) 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we have not yet set a server, or if the tips server is set to the wrong 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // locale, reset the server and force an immediate update of tips. 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_server_ = kDefaultResourceServer; 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_server_.append(locale); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_->SetString(prefs::kNTPTipsCacheUpdate, ""); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::EndFetch() { 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_fetch_ = false; 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::OnWebResourceUnpacked( 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& parsed_json) { 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get dictionary of cached preferences. 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_ = 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_->GetMutableDictionary(prefs::kNTPTipsCache); 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The list of individual tips. 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* tip_holder = new ListValue(); 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_->Set(WebResourceService::kTipCachePrefName, tip_holder); 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* topic_dict; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* answer_list; 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring topic_id; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring inproduct; 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tip_counter = 0; 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (parsed_json.GetDictionary(L"topic", &topic_dict)) { 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (topic_dict->GetString(L"topic_id", &topic_id)) 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_->SetString(L"topic_id", topic_id); 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (topic_dict->GetList(L"answers", &answer_list)) { 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (ListValue::const_iterator tip_iter = answer_list->begin(); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tip_iter != answer_list->end(); ++tip_iter) { 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* a_dic = 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<DictionaryValue*>(*tip_iter); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (a_dic->GetString(L"inproduct", &inproduct)) { 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tip_holder->Append(Value::CreateStringValue(inproduct)); 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tip_counter++; 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we have tips, set current tip to zero. 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!inproduct.empty()) 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_->SetInteger( 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebResourceService::kCurrentTipPrefName, 0); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EndFetch(); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::StartAfterDelay() { 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int delay = kStartResourceFetchDelay; 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check whether we have ever put a value in the web resource cache; 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // if so, pull it out and see if it's time to update again. 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (prefs_->HasPrefPath(prefs::kNTPTipsCacheUpdate)) { 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string last_update_pref = 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_->GetString(prefs::kNTPTipsCacheUpdate); 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!last_update_pref.empty()) { 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int ms_until_update = kCacheUpdateDelay - 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<int>((base::Time::Now() - base::Time::FromDoubleT( 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StringToDouble(last_update_pref))).InMilliseconds()); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay = ms_until_update > kCacheUpdateDelay ? 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCacheUpdateDelay : (ms_until_update < kStartResourceFetchDelay ? 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kStartResourceFetchDelay : ms_until_update); 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Start fetch and wait for UpdateResourceCache. 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_fetcher_->StartAfterDelay(static_cast<int>(delay)); 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::UpdateResourceCache(const std::string& json_data) { 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UnpackerClient* client = new UnpackerClient(this, json_data); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch client->Start(); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update resource server and cache update time in preferences. 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_->SetString(prefs::kNTPTipsCacheUpdate, 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DoubleToString(base::Time::Now().ToDoubleT())); 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch prefs_->SetString(prefs::kNTPTipsServer, web_resource_server_); 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 298