web_resource_service.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 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 772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include <string> 872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/command_line.h" 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/file_path.h" 113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_util.h" 123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/threading/thread_restrictions.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h" 18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/browser_thread.h" 1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h" 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/platform_util.h" 2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 22201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/browser/sync/sync_ui_util.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_switches.h" 24201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "chrome/common/extensions/extension.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/net/url_fetcher.h" 263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/notification_service.h" 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/common/notification_type.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/load_flags.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/url_request_status.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 33201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochnamespace { 34201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 35201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Delay on first fetch so we don't interfere with startup. 36201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstatic const int kStartResourceFetchDelay = 5000; 37201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 38201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Delay between calls to update the cache (48 hours). 39201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstatic const int kCacheUpdateDelay = 48 * 60 * 60 * 1000; 40201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Users are randomly assigned to one of kNTPPromoGroupSize buckets, in order 4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// to be able to roll out promos slowly, or display different promos to 4372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// different groups. 4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic const int kNTPPromoGroupSize = 16; 4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Maximum number of hours for each time slice (4 weeks). 4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic const int kMaxTimeSliceHours = 24 * 7 * 4; 4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Used to determine which build type should be shown a given promo. 5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenenum BuildType { 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DEV_BUILD = 1, 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen BETA_BUILD = 1 << 1, 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen STABLE_BUILD = 1 << 2, 5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 56201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} // namespace 57201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char* WebResourceService::kCurrentTipPrefName = "current_tip"; 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char* WebResourceService::kTipCachePrefName = "tips"; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebResourceService::WebResourceFetcher 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : public URLFetcher::Delegate { 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit WebResourceFetcher(WebResourceService* web_resource_service) : 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_factory_(this)), 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_(web_resource_service) { 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delay initial load of resource data into cache so as not to interfere 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // with startup time. 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void StartAfterDelay(int64 delay_ms) { 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch fetcher_factory_.NewRunnableMethod(&WebResourceFetcher::StartFetch), 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delay_ms); 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Initializes the fetching of data from the resource server. Data 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // load calls OnURLFetchComplete. 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartFetch() { 803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Balanced in OnURLFetchComplete. 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_service_->AddRef(); 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // First, put our next cache load on the MessageLoop. 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch fetcher_factory_.NewRunnableMethod(&WebResourceFetcher::StartFetch), 85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch web_resource_service_->cache_update_delay()); 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we are still fetching data, exit. 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (web_resource_service_->in_fetch_) 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->in_fetch_ = true; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string locale = g_browser_process->GetApplicationLocale(); 9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string web_resource_server = kDefaultWebResourceServer; 9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_resource_server.append(locale); 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_.reset(new URLFetcher(GURL( 9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_resource_server), 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch URLFetcher::GET, this)); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Do not let url fetcher affect existing state in profile (by setting 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cookies, for example. 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_->set_load_flags(net::LOAD_DISABLE_CACHE | 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net::LOAD_DO_NOT_SAVE_COOKIES); 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen URLRequestContextGetter* url_request_context_getter = 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_resource_service_->profile()->GetRequestContext(); 10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen url_fetcher_->set_request_context(url_request_context_getter); 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch url_fetcher_->Start(); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // From URLFetcher::Delegate. 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void OnURLFetchComplete(const URLFetcher* source, 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const GURL& url, 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const net::URLRequestStatus& status, 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int response_code, 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ResponseCookies& cookies, 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& data) { 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Delete the URLFetcher when this function exits. 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<URLFetcher> clean_up_fetcher(url_fetcher_.release()); 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't parse data if attempt to download was unsuccessful. 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Stop loading new web resource data, and silently exit. 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!status.is_success() || (response_code != 200)) 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->UpdateResourceCache(data); 1253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_service_->Release(); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // So that we can delay our start so as not to affect start-up time; also, 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so that we can schedule future cache updates. 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedRunnableMethodFactory<WebResourceFetcher> fetcher_factory_; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The tool that fetches the url data from the server. 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<URLFetcher> url_fetcher_; 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Our owner and creator. Ref counted. 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick WebResourceService* web_resource_service_; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This class coordinates a web resource unpack and parse task which is run in 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// a separate process. Results are sent back to this class and routed to 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the WebResourceService. 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass WebResourceService::UnpackerClient 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : public UtilityProcessHost::Client { 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UnpackerClient(WebResourceService* web_resource_service, 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& json_data) 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : web_resource_service_(web_resource_service), 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch json_data_(json_data), got_response_(false) { 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Start() { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AddRef(); // balanced in Cleanup. 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we don't have a resource_dispatcher_host_, assume we're in 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // a test and run the unpacker directly in-process. 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_utility_process = 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->resource_dispatcher_host_ != NULL && 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (use_utility_process) { 161731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::ID thread_id; 162731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id)); 163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask( 164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::IO, FROM_HERE, 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod(this, &UnpackerClient::StartProcessOnIOThread, 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->resource_dispatcher_host_, 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch thread_id)); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebResourceUnpacker unpacker(json_data_); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (unpacker.Run()) { 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnUnpackWebResourceSucceeded(*unpacker.parsed_json()); 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnUnpackWebResourceFailed(unpacker.error_message()); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ~UnpackerClient() {} 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // UtilityProcessHost::Client 18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen virtual void OnProcessCrashed(int exit_code) { 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (got_response_) 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OnUnpackWebResourceFailed( 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Chrome crashed while trying to retrieve web resources."); 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnUnpackWebResourceSucceeded( 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& parsed_json) { 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->OnWebResourceUnpacked(parsed_json); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Cleanup(); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnUnpackWebResourceFailed(const std::string& error_message) { 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_service_->EndFetch(); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Cleanup(); 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Release reference and set got_response_. 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Cleanup() { 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (got_response_) 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch got_response_ = true; 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Release(); 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartProcessOnIOThread(ResourceDispatcherHost* rdh, 211731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::ID thread_id) { 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UtilityProcessHost* host = new UtilityProcessHost(rdh, this, thread_id); 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(mrc): get proper file path when we start using web resources 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that need to be unpacked. 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch host->StartWebResourceUnpacker(json_data_); 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_refptr<WebResourceService> web_resource_service_; 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Holds raw JSON string. 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& json_data_; 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // True if we got a response from the utility process and have cleaned up 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // already. 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool got_response_; 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Server for dynamically loaded NTP HTML elements. TODO(mirandac): append 229201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// locale for future usage, when we're serving localizable strings. 230201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst char* WebResourceService::kDefaultWebResourceServer = 23172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "https://www.google.com/support/chrome/bin/topic/1142433/inproduct?hl="; 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebResourceService::WebResourceService(Profile* profile) 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : prefs_(profile->GetPrefs()), 235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch profile_(profile), 236201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ALLOW_THIS_IN_INITIALIZER_LIST(service_factory_(this)), 237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch in_fetch_(false), 238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch web_resource_update_scheduled_(false) { 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Init(); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWebResourceService::~WebResourceService() { } 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::Init() { 245201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch cache_update_delay_ = kCacheUpdateDelay; 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host(); 2473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_fetcher_.reset(new WebResourceFetcher(this)); 2483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->RegisterStringPref(prefs::kNTPWebResourceCacheUpdate, "0"); 24972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->RegisterDoublePref(prefs::kNTPCustomLogoStart, 0); 25072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->RegisterDoublePref(prefs::kNTPCustomLogoEnd, 0); 25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->RegisterDoublePref(prefs::kNTPPromoStart, 0); 25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->RegisterDoublePref(prefs::kNTPPromoEnd, 0); 253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch prefs_->RegisterStringPref(prefs::kNTPPromoLine, std::string()); 254201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch prefs_->RegisterBooleanPref(prefs::kNTPPromoClosed, false); 25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->RegisterIntegerPref(prefs::kNTPPromoGroup, -1); 25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->RegisterIntegerPref(prefs::kNTPPromoBuild, 25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DEV_BUILD | BETA_BUILD | STABLE_BUILD); 25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->RegisterIntegerPref(prefs::kNTPPromoGroupTimeSlice, 0); 259201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 260201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // If the promo start is in the future, set a notification task to invalidate 261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // the NTP cache at the time of the promo start. 26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen double promo_start = prefs_->GetDouble(prefs::kNTPPromoStart); 26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen double promo_end = prefs_->GetDouble(prefs::kNTPPromoEnd); 264201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ScheduleNotification(promo_start, promo_end); 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::EndFetch() { 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_fetch_ = false; 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WebResourceService::OnWebResourceUnpacked( 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const DictionaryValue& parsed_json) { 2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UnpackLogoSignal(parsed_json); 27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UnpackPromoSignal(parsed_json); 2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick EndFetch(); 2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 278201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid WebResourceService::WebResourceStateChange() { 279201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch web_resource_update_scheduled_ = false; 280201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch NotificationService* service = NotificationService::current(); 281201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch service->Notify(NotificationType::WEB_RESOURCE_STATE_CHANGED, 282201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch Source<WebResourceService>(this), 283201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch NotificationService::NoDetails()); 284201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 285201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 286201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid WebResourceService::ScheduleNotification(double promo_start, 287201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch double promo_end) { 288201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (promo_start > 0 && promo_end > 0 && !web_resource_update_scheduled_) { 28972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int64 ms_until_start = 29072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static_cast<int64>((base::Time::FromDoubleT( 291201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch promo_start) - base::Time::Now()).InMilliseconds()); 29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int64 ms_until_end = 29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static_cast<int64>((base::Time::FromDoubleT( 294201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch promo_end) - base::Time::Now()).InMilliseconds()); 295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (ms_until_start > 0) { 296201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch web_resource_update_scheduled_ = true; 297201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 298201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch service_factory_.NewRunnableMethod( 299201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &WebResourceService::WebResourceStateChange), 300201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ms_until_start); 301201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 302201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (ms_until_end > 0) { 303201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch web_resource_update_scheduled_ = true; 304201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 305201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch service_factory_.NewRunnableMethod( 306201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch &WebResourceService::WebResourceStateChange), 307201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ms_until_end); 308201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (ms_until_start <= 0) { 309201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Notify immediately if time is between start and end. 310201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch WebResourceStateChange(); 311201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 312201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 313201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 314201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 315201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 3163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebResourceService::StartAfterDelay() { 31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int64 delay = kStartResourceFetchDelay; 3183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check whether we have ever put a value in the web resource cache; 3193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // if so, pull it out and see if it's time to update again. 3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (prefs_->HasPrefPath(prefs::kNTPWebResourceCacheUpdate)) { 3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string last_update_pref = 3223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->GetString(prefs::kNTPWebResourceCacheUpdate); 3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!last_update_pref.empty()) { 3243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double last_update_value; 3253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::StringToDouble(last_update_pref, &last_update_value); 32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int64 ms_until_update = cache_update_delay_ - 32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static_cast<int64>((base::Time::Now() - base::Time::FromDoubleT( 3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick last_update_value)).InMilliseconds()); 329201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch delay = ms_until_update > cache_update_delay_ ? 330201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch cache_update_delay_ : (ms_until_update < kStartResourceFetchDelay ? 331201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch kStartResourceFetchDelay : ms_until_update); 3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Start fetch and wait for UpdateResourceCache. 33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_resource_fetcher_->StartAfterDelay(delay); 3363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebResourceService::UpdateResourceCache(const std::string& json_data) { 3393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UnpackerClient* client = new UnpackerClient(this, json_data); 3403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick client->Start(); 3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 342201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Set cache update time in preferences. 3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->SetString(prefs::kNTPWebResourceCacheUpdate, 3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::DoubleToString(base::Time::Now().ToDoubleT())); 3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebResourceService::UnpackTips(const DictionaryValue& parsed_json) { 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Get dictionary of cached preferences. 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_ = 3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->GetMutableDictionary(prefs::kNTPWebResourceCache); 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The list of individual tips. 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* tip_holder = new ListValue(); 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_->Set(WebResourceService::kTipCachePrefName, tip_holder); 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* topic_dict; 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ListValue* answer_list; 3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string topic_id; 3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string answer_id; 3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string inproduct; 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int tip_counter = 0; 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (parsed_json.GetDictionary("topic", &topic_dict)) { 3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (topic_dict->GetString("topic_id", &topic_id)) 3653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick web_resource_cache_->SetString("topic_id", topic_id); 3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (topic_dict->GetList("answers", &answer_list)) { 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (ListValue::const_iterator tip_iter = answer_list->begin(); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tip_iter != answer_list->end(); ++tip_iter) { 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DictionaryValue* a_dic = 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<DictionaryValue*>(*tip_iter); 3733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (a_dic->GetString("inproduct", &inproduct)) { 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tip_holder->Append(Value::CreateStringValue(inproduct)); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch tip_counter++; 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // If tips exist, set current index to 0. 3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!inproduct.empty()) { 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_resource_cache_->SetInteger( 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebResourceService::kCurrentTipPrefName, 0); 3823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 387201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid WebResourceService::UnpackPromoSignal(const DictionaryValue& parsed_json) { 388201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DictionaryValue* topic_dict; 389201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ListValue* answer_list; 390201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch double old_promo_start = 0; 391201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch double old_promo_end = 0; 392201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch double promo_start = 0; 393201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch double promo_end = 0; 394201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 395201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Check for preexisting start and end values. 396201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (prefs_->HasPrefPath(prefs::kNTPPromoStart) && 397201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch prefs_->HasPrefPath(prefs::kNTPPromoEnd)) { 39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen old_promo_start = prefs_->GetDouble(prefs::kNTPPromoStart); 39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen old_promo_end = prefs_->GetDouble(prefs::kNTPPromoEnd); 400201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 401201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 402201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Check for newly received start and end values. 403201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (parsed_json.GetDictionary("topic", &topic_dict)) { 404201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (topic_dict->GetList("answers", &answer_list)) { 405201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::string promo_start_string = ""; 406201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::string promo_end_string = ""; 407201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::string promo_string = ""; 40872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string promo_build = ""; 40972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int promo_build_type = 0; 41072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int time_slice_hrs = 0; 411201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (ListValue::const_iterator tip_iter = answer_list->begin(); 412201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch tip_iter != answer_list->end(); ++tip_iter) { 413201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) 414201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch continue; 415201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DictionaryValue* a_dic = 416201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch static_cast<DictionaryValue*>(*tip_iter); 417201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch std::string promo_signal; 418201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (a_dic->GetString("name", &promo_signal)) { 419201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (promo_signal == "promo_start") { 42072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen a_dic->GetString("question", &promo_build); 42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t split = promo_build.find(":"); 42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (split != std::string::npos && 42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::StringToInt(promo_build.substr(0, split), 42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &promo_build_type) && 42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::StringToInt(promo_build.substr(split+1), 42672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &time_slice_hrs) && 42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen promo_build_type >= 0 && 42872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen promo_build_type <= (DEV_BUILD | BETA_BUILD | STABLE_BUILD) && 42972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen time_slice_hrs >= 0 && 43072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen time_slice_hrs <= kMaxTimeSliceHours) { 43172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetInteger(prefs::kNTPPromoBuild, promo_build_type); 43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, 43372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen time_slice_hrs); 43472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 43572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If no time data or bad time data are set, show promo on all 43672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // builds with no time slicing. 43772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetInteger(prefs::kNTPPromoBuild, 43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DEV_BUILD | BETA_BUILD | STABLE_BUILD); 43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, 0); 44072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 441201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch a_dic->GetString("inproduct", &promo_start_string); 442201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch a_dic->GetString("tooltip", &promo_string); 443201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch prefs_->SetString(prefs::kNTPPromoLine, promo_string); 44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen srand(static_cast<uint32>(time(NULL))); 44572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetInteger(prefs::kNTPPromoGroup, 44672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rand() % kNTPPromoGroupSize); 447201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } else if (promo_signal == "promo_end") { 448201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch a_dic->GetString("inproduct", &promo_end_string); 449201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 450201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 451201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 452201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!promo_start_string.empty() && 453201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch promo_start_string.length() > 0 && 454201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch !promo_end_string.empty() && 455201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch promo_end_string.length() > 0) { 456201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch base::Time start_time; 457201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch base::Time end_time; 458201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (base::Time::FromString( 459201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ASCIIToWide(promo_start_string).c_str(), &start_time) && 460201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch base::Time::FromString( 461201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ASCIIToWide(promo_end_string).c_str(), &end_time)) { 46272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Add group time slice, adjusted from hours to seconds. 46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen promo_start = start_time.ToDoubleT() + 46472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (prefs_->FindPreference(prefs::kNTPPromoGroup) ? 46572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->GetInteger(prefs::kNTPPromoGroup) * 46672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen time_slice_hrs * 60 * 60 : 0); 467201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch promo_end = end_time.ToDoubleT(); 468201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 469201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 470201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 472201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 473201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // If start or end times have changed, trigger a new web resource 474201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // notification, so that the logo on the NTP is updated. This check is 475201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // outside the reading of the web resource data, because the absence of 476201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // dates counts as a triggering change if there were dates before. 47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Also reset the promo closed preference, to signal a new promo. 478201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (!(old_promo_start == promo_start) || 479201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch !(old_promo_end == promo_end)) { 48072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetDouble(prefs::kNTPPromoStart, promo_start); 48172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetDouble(prefs::kNTPPromoEnd, promo_end); 48272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetBoolean(prefs::kNTPPromoClosed, false); 483201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch ScheduleNotification(promo_start, promo_end); 484201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 485201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 486201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 4873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WebResourceService::UnpackLogoSignal(const DictionaryValue& parsed_json) { 4883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DictionaryValue* topic_dict; 4893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ListValue* answer_list; 4903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double old_logo_start = 0; 4913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double old_logo_end = 0; 4923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double logo_start = 0; 4933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick double logo_end = 0; 4943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check for preexisting start and end values. 4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (prefs_->HasPrefPath(prefs::kNTPCustomLogoStart) && 4973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick prefs_->HasPrefPath(prefs::kNTPCustomLogoEnd)) { 49872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen old_logo_start = prefs_->GetDouble(prefs::kNTPCustomLogoStart); 49972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen old_logo_end = prefs_->GetDouble(prefs::kNTPCustomLogoEnd); 5003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Check for newly received start and end values. 5033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (parsed_json.GetDictionary("topic", &topic_dict)) { 5043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (topic_dict->GetList("answers", &answer_list)) { 5053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string logo_start_string = ""; 5063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string logo_end_string = ""; 5073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (ListValue::const_iterator tip_iter = answer_list->begin(); 5083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick tip_iter != answer_list->end(); ++tip_iter) { 5093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) 5103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick continue; 5113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DictionaryValue* a_dic = 5123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static_cast<DictionaryValue*>(*tip_iter); 5133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string logo_signal; 5143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (a_dic->GetString("name", &logo_signal)) { 5153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (logo_signal == "custom_logo_start") { 5163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a_dic->GetString("inproduct", &logo_start_string); 5173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else if (logo_signal == "custom_logo_end") { 5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick a_dic->GetString("inproduct", &logo_end_string); 5193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 5203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!logo_start_string.empty() && 5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick logo_start_string.length() > 0 && 5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick !logo_end_string.empty() && 5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick logo_end_string.length() > 0) { 5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::Time start_time; 5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::Time end_time; 5283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (base::Time::FromString( 5293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASCIIToWide(logo_start_string).c_str(), &start_time) && 5303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::Time::FromString( 5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASCIIToWide(logo_end_string).c_str(), &end_time)) { 5323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick logo_start = start_time.ToDoubleT(); 5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick logo_end = end_time.ToDoubleT(); 5343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 5353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 539731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If logo start or end times have changed, trigger a new web resource 540731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // notification, so that the logo on the NTP is updated. This check is 541731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // outside the reading of the web resource data, because the absence of 542731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // dates counts as a triggering change if there were dates before. 5433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!(old_logo_start == logo_start) || 5443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick !(old_logo_end == logo_end)) { 54572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetDouble(prefs::kNTPCustomLogoStart, logo_start); 54672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen prefs_->SetDouble(prefs::kNTPCustomLogoEnd, logo_end); 5473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationService* service = NotificationService::current(); 548201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch service->Notify(NotificationType::WEB_RESOURCE_STATE_CHANGED, 5493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Source<WebResourceService>(this), 5503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NotificationService::NoDetails()); 5513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 553201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 554201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochnamespace WebResourceServiceUtil { 555201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 556201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochbool CanShowPromo(Profile* profile) { 557201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch bool promo_closed = false; 558201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch PrefService* prefs = profile->GetPrefs(); 559201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (prefs->HasPrefPath(prefs::kNTPPromoClosed)) 560201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch promo_closed = prefs->GetBoolean(prefs::kNTPPromoClosed); 561201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 56272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Only show if not synced. 56372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool is_synced = 564201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch (profile->HasProfileSyncService() && 565201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch sync_ui_util::GetStatus( 56672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen profile->GetProfileSyncService()) == sync_ui_util::SYNCED); 56772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 56872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // GetVersionStringModifier hits the registry. See http://crbug.com/70898. 56972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::ThreadRestrictions::ScopedAllowIO allow_io; 57072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string channel = platform_util::GetVersionStringModifier(); 57172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool is_promo_build = false; 57272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (prefs->HasPrefPath(prefs::kNTPPromoBuild)) { 57372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int builds_allowed = prefs->GetInteger(prefs::kNTPPromoBuild); 57472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (channel == "dev") { 57572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen is_promo_build = (DEV_BUILD & builds_allowed) != 0; 57672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (channel == "beta") { 57772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen is_promo_build = (BETA_BUILD & builds_allowed) != 0; 57872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (channel == "stable") { 57972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen is_promo_build = (STABLE_BUILD & builds_allowed) != 0; 58072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 58172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen is_promo_build = true; 58272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 58372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 584201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 58572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return !promo_closed && !is_synced && is_promo_build; 586201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 587201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 588201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} // namespace WebResourceService 589201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 590