web_resource_service.cc revision 731df977c0511bca2206b5f333555b1205ff1f43
13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 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. 43345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/web_resource/web_resource_service.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h" 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/file_path.h" 93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 15731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/browser_thread.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/profile.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/net/url_fetcher.h" 193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/notification_service.h" 203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/notification_type.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/load_flags.h" 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_status.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char* WebResourceService::kCurrentTipPrefName = "current_tip"; 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char* WebResourceService::kTipCachePrefName = "tips"; 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebResourceService::WebResourceFetcher 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : public URLFetcher::Delegate { 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit WebResourceFetcher(WebResourceService* web_resource_service) : 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_factory_(this)), 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_(web_resource_service) { 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delay initial load of resource data into cache so as not to interfere 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with startup time. 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartAfterDelay(int delay_ms) { 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fetcher_factory_.NewRunnableMethod(&WebResourceFetcher::StartFetch), 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay_ms); 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Initializes the fetching of data from the resource server. Data 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // load calls OnURLFetchComplete. 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartFetch() { 483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Balanced in OnURLFetchComplete. 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_service_->AddRef(); 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First, put our next cache load on the MessageLoop. 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fetcher_factory_.NewRunnableMethod(&WebResourceFetcher::StartFetch), 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCacheUpdateDelay); 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we are still fetching data, exit. 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (web_resource_service_->in_fetch_) 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->in_fetch_ = true; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_.reset(new URLFetcher(GURL( 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->web_resource_server_), 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLFetcher::GET, this)); 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do not let url fetcher affect existing state in profile (by setting 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cookies, for example. 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_->set_load_flags(net::LOAD_DISABLE_CACHE | 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::LOAD_DO_NOT_SAVE_COOKIES); 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_->set_request_context(Profile::GetDefaultRequestContext()); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_->Start(); 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // From URLFetcher::Delegate. 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnURLFetchComplete(const URLFetcher* source, 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const URLRequestStatus& status, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int response_code, 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ResponseCookies& cookies, 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& data) { 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete the URLFetcher when this function exits. 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<URLFetcher> clean_up_fetcher(url_fetcher_.release()); 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't parse data if attempt to download was unsuccessful. 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Stop loading new web resource data, and silently exit. 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!status.is_success() || (response_code != 200)) 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->UpdateResourceCache(data); 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_service_->Release(); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // So that we can delay our start so as not to affect start-up time; also, 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so that we can schedule future cache updates. 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedRunnableMethodFactory<WebResourceFetcher> fetcher_factory_; 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tool that fetches the url data from the server. 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<URLFetcher> url_fetcher_; 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Our owner and creator. Ref counted. 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick WebResourceService* web_resource_service_; 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class coordinates a web resource unpack and parse task which is run in 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a separate process. Results are sent back to this class and routed to 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the WebResourceService. 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebResourceService::UnpackerClient 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : public UtilityProcessHost::Client { 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UnpackerClient(WebResourceService* web_resource_service, 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& json_data) 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : web_resource_service_(web_resource_service), 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch json_data_(json_data), got_response_(false) { 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Start() { 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // balanced in Cleanup. 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we don't have a resource_dispatcher_host_, assume we're in 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a test and run the unpacker directly in-process. 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_utility_process = 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->resource_dispatcher_host_ != NULL && 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (use_utility_process) { 123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::ID thread_id; 124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id)); 125731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 126731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &UnpackerClient::StartProcessOnIOThread, 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->resource_dispatcher_host_, 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thread_id)); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebResourceUnpacker unpacker(json_data_); 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (unpacker.Run()) { 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnUnpackWebResourceSucceeded(*unpacker.parsed_json()); 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnUnpackWebResourceFailed(unpacker.error_message()); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~UnpackerClient() {} 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // UtilityProcessHost::Client 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnProcessCrashed() { 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (got_response_) 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnUnpackWebResourceFailed( 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Chrome crashed while trying to retrieve web resources."); 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnUnpackWebResourceSucceeded( 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& parsed_json) { 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->OnWebResourceUnpacked(parsed_json); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Cleanup(); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnUnpackWebResourceFailed(const std::string& error_message) { 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->EndFetch(); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Cleanup(); 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Release reference and set got_response_. 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Cleanup() { 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (got_response_) 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch got_response_ = true; 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartProcessOnIOThread(ResourceDispatcherHost* rdh, 173731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::ID thread_id) { 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UtilityProcessHost* host = new UtilityProcessHost(rdh, this, thread_id); 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(mrc): get proper file path when we start using web resources 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that need to be unpacked. 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch host->StartWebResourceUnpacker(json_data_); 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<WebResourceService> web_resource_service_; 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Holds raw JSON string. 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& json_data_; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // True if we got a response from the utility process and have cleaned up 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // already. 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool got_response_; 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Server for custom logo signals. 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char* WebResourceService::kDefaultResourceServer = 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "https://www.google.com/support/chrome/bin/topic/30248/inproduct"; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebResourceService::WebResourceService(Profile* profile) 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : prefs_(profile->GetPrefs()), 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_fetch_(false) { 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Init(); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebResourceService::~WebResourceService() { } 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::Init() { 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host(); 2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_fetcher_.reset(new WebResourceFetcher(this)); 2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->RegisterStringPref(prefs::kNTPWebResourceCacheUpdate, "0"); 2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->RegisterRealPref(prefs::kNTPCustomLogoStart, 0); 2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->RegisterRealPref(prefs::kNTPCustomLogoEnd, 0); 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (prefs_->HasPrefPath(prefs::kNTPLogoResourceServer)) { 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_server_ = prefs_->GetString(prefs::kNTPLogoResourceServer); 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If we have not yet set a server, reset and force an immediate update. 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_server_ = kDefaultResourceServer; 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->SetString(prefs::kNTPWebResourceCacheUpdate, ""); 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::EndFetch() { 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_fetch_ = false; 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::OnWebResourceUnpacked( 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& parsed_json) { 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UnpackLogoSignal(parsed_json); 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EndFetch(); 2273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebResourceService::StartAfterDelay() { 2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int delay = kStartResourceFetchDelay; 2313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check whether we have ever put a value in the web resource cache; 2323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // if so, pull it out and see if it's time to update again. 2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (prefs_->HasPrefPath(prefs::kNTPWebResourceCacheUpdate)) { 2343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string last_update_pref = 2353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->GetString(prefs::kNTPWebResourceCacheUpdate); 2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!last_update_pref.empty()) { 2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double last_update_value; 2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::StringToDouble(last_update_pref, &last_update_value); 2393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int ms_until_update = kCacheUpdateDelay - 2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<int>((base::Time::Now() - base::Time::FromDoubleT( 2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick last_update_value)).InMilliseconds()); 2423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick delay = ms_until_update > kCacheUpdateDelay ? 2443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kCacheUpdateDelay : (ms_until_update < kStartResourceFetchDelay ? 2453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick kStartResourceFetchDelay : ms_until_update); 2463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Start fetch and wait for UpdateResourceCache. 2503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_fetcher_->StartAfterDelay(static_cast<int>(delay)); 2513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebResourceService::UpdateResourceCache(const std::string& json_data) { 2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UnpackerClient* client = new UnpackerClient(this, json_data); 2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick client->Start(); 2563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Update resource server and cache update time in preferences. 2583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->SetString(prefs::kNTPWebResourceCacheUpdate, 2593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::DoubleToString(base::Time::Now().ToDoubleT())); 2603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->SetString(prefs::kNTPLogoResourceServer, web_resource_server_); 2613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebResourceService::UnpackTips(const DictionaryValue& parsed_json) { 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get dictionary of cached preferences. 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_ = 2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->GetMutableDictionary(prefs::kNTPWebResourceCache); 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The list of individual tips. 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* tip_holder = new ListValue(); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_->Set(WebResourceService::kTipCachePrefName, tip_holder); 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* topic_dict; 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* answer_list; 2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string topic_id; 2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string answer_id; 2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string inproduct; 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tip_counter = 0; 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (parsed_json.GetDictionary("topic", &topic_dict)) { 2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (topic_dict->GetString("topic_id", &topic_id)) 2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_cache_->SetString("topic_id", topic_id); 2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (topic_dict->GetList("answers", &answer_list)) { 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (ListValue::const_iterator tip_iter = answer_list->begin(); 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tip_iter != answer_list->end(); ++tip_iter) { 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* a_dic = 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<DictionaryValue*>(*tip_iter); 2893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (a_dic->GetString("inproduct", &inproduct)) { 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tip_holder->Append(Value::CreateStringValue(inproduct)); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tip_counter++; 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If tips exist, set current index to 0. 2953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!inproduct.empty()) { 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_->SetInteger( 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebResourceService::kCurrentTipPrefName, 0); 2983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebResourceService::UnpackLogoSignal(const DictionaryValue& parsed_json) { 3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DictionaryValue* topic_dict; 3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ListValue* answer_list; 3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double old_logo_start = 0; 3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double old_logo_end = 0; 3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double logo_start = 0; 3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double logo_end = 0; 3103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check for preexisting start and end values. 3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (prefs_->HasPrefPath(prefs::kNTPCustomLogoStart) && 3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->HasPrefPath(prefs::kNTPCustomLogoEnd)) { 3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick old_logo_start = prefs_->GetReal(prefs::kNTPCustomLogoStart); 3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick old_logo_end = prefs_->GetReal(prefs::kNTPCustomLogoEnd); 3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check for newly received start and end values. 3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (parsed_json.GetDictionary("topic", &topic_dict)) { 3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (topic_dict->GetList("answers", &answer_list)) { 3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string logo_start_string = ""; 3223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string logo_end_string = ""; 3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (ListValue::const_iterator tip_iter = answer_list->begin(); 3243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick tip_iter != answer_list->end(); ++tip_iter) { 3253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) 3263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick continue; 3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DictionaryValue* a_dic = 3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<DictionaryValue*>(*tip_iter); 3293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string logo_signal; 3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (a_dic->GetString("name", &logo_signal)) { 3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (logo_signal == "custom_logo_start") { 3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a_dic->GetString("inproduct", &logo_start_string); 3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (logo_signal == "custom_logo_end") { 3343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a_dic->GetString("inproduct", &logo_end_string); 3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!logo_start_string.empty() && 3393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick logo_start_string.length() > 0 && 3403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick !logo_end_string.empty() && 3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick logo_end_string.length() > 0) { 3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::Time start_time; 3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::Time end_time; 3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (base::Time::FromString( 3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASCIIToWide(logo_start_string).c_str(), &start_time) && 3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::Time::FromString( 3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASCIIToWide(logo_end_string).c_str(), &end_time)) { 3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick logo_start = start_time.ToDoubleT(); 3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick logo_end = end_time.ToDoubleT(); 3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 355731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If logo start or end times have changed, trigger a new web resource 356731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // notification, so that the logo on the NTP is updated. This check is 357731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // outside the reading of the web resource data, because the absence of 358731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // dates counts as a triggering change if there were dates before. 3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!(old_logo_start == logo_start) || 3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick !(old_logo_end == logo_end)) { 3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->SetReal(prefs::kNTPCustomLogoStart, logo_start); 3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->SetReal(prefs::kNTPCustomLogoEnd, logo_end); 3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationService* service = NotificationService::current(); 364731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick service->Notify(NotificationType::WEB_RESOURCE_AVAILABLE, 3653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<WebResourceService>(this), 3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationService::NoDetails()); 3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 369