Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: chrome/browser/web_resource/web_resource_service.cc

Issue 8851007: WIP / Do not commit (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/web_resource/web_resource_service.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/web_resource/web_resource_service.h" 5 #include "chrome/browser/web_resource/web_resource_service.h"
6 6
7 #include "base/bind.h"
7 #include "base/command_line.h" 8 #include "base/command_line.h"
8 #include "base/file_path.h"
9 #include "base/string_number_conversions.h" 9 #include "base/string_number_conversions.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
11 #include "base/threading/thread_restrictions.h"
12 #include "base/time.h" 11 #include "base/time.h"
13 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
14 #include "base/values.h" 13 #include "base/values.h"
15 #include "chrome/browser/browser_process.h" 14 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/prefs/pref_service.h" 15 #include "chrome/browser/prefs/pref_service.h"
17 #include "chrome/browser/sync/sync_ui_util.h"
18 #include "chrome/common/chrome_notification_types.h"
19 #include "chrome/common/chrome_switches.h" 16 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/chrome_utility_messages.h" 17 #include "chrome/common/chrome_utility_messages.h"
21 #include "chrome/common/extensions/extension.h"
22 #include "chrome/common/web_resource/web_resource_unpacker.h" 18 #include "chrome/common/web_resource/web_resource_unpacker.h"
19 #include "content/browser/utility_process_host.h"
23 #include "content/public/browser/browser_thread.h" 20 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_service.h"
25 #include "content/public/common/url_fetcher.h" 21 #include "content/public/common/url_fetcher.h"
26 #include "content/public/common/url_fetcher_delegate.h"
27 #include "googleurl/src/gurl.h" 22 #include "googleurl/src/gurl.h"
28 #include "net/base/load_flags.h" 23 #include "net/base/load_flags.h"
29 #include "net/url_request/url_request_status.h" 24 #include "net/url_request/url_request_status.h"
30 25
31 using content::BrowserThread; 26 using content::BrowserThread;
32 27
33 class WebResourceService::WebResourceFetcher
34 : public content::URLFetcherDelegate {
35 public:
36 explicit WebResourceFetcher(WebResourceService* web_resource_service) :
37 ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_factory_(this)),
38 web_resource_service_(web_resource_service) {
39 }
40
41 // Delay initial load of resource data into cache so as not to interfere
42 // with startup time.
43 void StartAfterDelay(int64 delay_ms) {
44 MessageLoop::current()->PostDelayedTask(FROM_HERE,
45 fetcher_factory_.NewRunnableMethod(&WebResourceFetcher::StartFetch),
46 delay_ms);
47 }
48
49 // Initializes the fetching of data from the resource server. Data
50 // load calls OnURLFetchComplete.
51 void StartFetch() {
52 // Balanced in OnURLFetchComplete.
53 web_resource_service_->AddRef();
54 // First, put our next cache load on the MessageLoop.
55 MessageLoop::current()->PostDelayedTask(FROM_HERE,
56 fetcher_factory_.NewRunnableMethod(&WebResourceFetcher::StartFetch),
57 web_resource_service_->cache_update_delay_);
58 // If we are still fetching data, exit.
59 if (web_resource_service_->in_fetch_)
60 return;
61 else
62 web_resource_service_->in_fetch_ = true;
63
64 std::string web_resource_server =
65 web_resource_service_->web_resource_server_;
66 if (web_resource_service_->apply_locale_to_url_) {
67 std::string locale = g_browser_process->GetApplicationLocale();
68 web_resource_server.append(locale);
69 }
70
71 url_fetcher_.reset(content::URLFetcher::Create(
72 GURL(web_resource_server), content::URLFetcher::GET, this));
73 // Do not let url fetcher affect existing state in system context (by
74 // setting cookies, for example).
75 url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE |
76 net::LOAD_DO_NOT_SAVE_COOKIES);
77 net::URLRequestContextGetter* url_request_context_getter =
78 g_browser_process->system_request_context();
79 url_fetcher_->SetRequestContext(url_request_context_getter);
80 url_fetcher_->Start();
81 }
82
83 // From content::URLFetcherDelegate.
84 void OnURLFetchComplete(const content::URLFetcher* source) {
85 // Delete the URLFetcher when this function exits.
86 scoped_ptr<content::URLFetcher> clean_up_fetcher(url_fetcher_.release());
87
88 // Don't parse data if attempt to download was unsuccessful.
89 // Stop loading new web resource data, and silently exit.
90 if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200))
91 return;
92
93 std::string data;
94 source->GetResponseAsString(&data);
95 web_resource_service_->UpdateResourceCache(data);
96 web_resource_service_->Release();
97 }
98
99 private:
100 // So that we can delay our start so as not to affect start-up time; also,
101 // so that we can schedule future cache updates.
102 ScopedRunnableMethodFactory<WebResourceFetcher> fetcher_factory_;
103
104 // The tool that fetches the url data from the server.
105 scoped_ptr<content::URLFetcher> url_fetcher_;
106
107 // Our owner and creator. Ref counted.
108 WebResourceService* web_resource_service_;
109 };
110
111 // This class coordinates a web resource unpack and parse task which is run in 28 // This class coordinates a web resource unpack and parse task which is run in
112 // a separate process. Results are sent back to this class and routed to 29 // a separate process. Results are sent back to this class and routed to
113 // the WebResourceService. 30 // the WebResourceService.
114 class WebResourceService::UnpackerClient : public UtilityProcessHost::Client { 31 class WebResourceService::UnpackerClient : public UtilityProcessHost::Client {
115 public: 32 public:
116 UnpackerClient(WebResourceService* web_resource_service, 33 explicit UnpackerClient(WebResourceService* web_resource_service)
117 const std::string& json_data)
118 : web_resource_service_(web_resource_service), 34 : web_resource_service_(web_resource_service),
119 json_data_(json_data), got_response_(false) { 35 resource_dispatcher_host_(g_browser_process->resource_dispatcher_host()),
36 got_response_(false) {
120 } 37 }
121 38
122 void Start() { 39 void Start(const std::string& json_data) {
123 AddRef(); // balanced in Cleanup. 40 AddRef(); // balanced in Cleanup.
124 41
125 // TODO(willchan): Look for a better signal of whether we're in a unit test 42 // TODO(willchan): Look for a better signal of whether we're in a unit test
126 // or not. Using |resource_dispatcher_host_| for this is pretty lame. 43 // or not. Using |resource_dispatcher_host_| for this is pretty lame.
127 // If we don't have a resource_dispatcher_host_, assume we're in 44 // If we don't have a resource_dispatcher_host_, assume we're in
128 // a test and run the unpacker directly in-process. 45 // a test and run the unpacker directly in-process.
129 bool use_utility_process = 46 bool use_utility_process =
130 web_resource_service_->resource_dispatcher_host_ != NULL && 47 resource_dispatcher_host_ != NULL &&
131 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); 48 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
132 if (use_utility_process) { 49 if (use_utility_process) {
133 BrowserThread::ID thread_id; 50 BrowserThread::ID thread_id;
134 CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id)); 51 CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id));
135 BrowserThread::PostTask( 52 BrowserThread::PostTask(
136 BrowserThread::IO, FROM_HERE, 53 BrowserThread::IO, FROM_HERE,
137 NewRunnableMethod(this, &UnpackerClient::StartProcessOnIOThread, 54 base::Bind(&UnpackerClient::StartProcessOnIOThread,
138 thread_id)); 55 this, thread_id, json_data));
139 } else { 56 } else {
140 WebResourceUnpacker unpacker(json_data_); 57 WebResourceUnpacker unpacker(json_data);
141 if (unpacker.Run()) { 58 if (unpacker.Run()) {
142 OnUnpackWebResourceSucceeded(*unpacker.parsed_json()); 59 OnUnpackWebResourceSucceeded(*unpacker.parsed_json());
143 } else { 60 } else {
144 OnUnpackWebResourceFailed(unpacker.error_message()); 61 OnUnpackWebResourceFailed(unpacker.error_message());
145 } 62 }
146 } 63 }
147 } 64 }
148 65
149 private: 66 private:
150 virtual ~UnpackerClient() {} 67 virtual ~UnpackerClient() {}
151 68
152 // UtilityProcessHost::Client 69 // UtilityProcessHost::Client
153 virtual bool OnMessageReceived(const IPC::Message& message) { 70 virtual bool OnMessageReceived(const IPC::Message& message) {
154 bool msg_is_ok = true;
155 bool handled = true; 71 bool handled = true;
156 IPC_BEGIN_MESSAGE_MAP_EX(WebResourceService::UnpackerClient, message, 72 IPC_BEGIN_MESSAGE_MAP(WebResourceService::UnpackerClient, message)
157 msg_is_ok)
158 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Succeeded, 73 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Succeeded,
159 OnUnpackWebResourceSucceeded) 74 OnUnpackWebResourceSucceeded)
160 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Failed, 75 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Failed,
161 OnUnpackWebResourceFailed) 76 OnUnpackWebResourceFailed)
162 IPC_MESSAGE_UNHANDLED(handled = false) 77 IPC_MESSAGE_UNHANDLED(handled = false)
163 IPC_END_MESSAGE_MAP_EX() 78 IPC_END_MESSAGE_MAP_EX()
164 return handled; 79 return handled;
165 } 80 }
166 81
167 virtual void OnProcessCrashed(int exit_code) { 82 virtual void OnProcessCrashed(int exit_code) {
168 if (got_response_) 83 if (got_response_)
169 return; 84 return;
170 85
171 OnUnpackWebResourceFailed( 86 OnUnpackWebResourceFailed(
172 "Chrome crashed while trying to retrieve web resources."); 87 "Utility process crashed while trying to retrieve web resources.");
173 } 88 }
174 89
175 void OnUnpackWebResourceSucceeded( 90 void OnUnpackWebResourceSucceeded(
176 const DictionaryValue& parsed_json) { 91 const DictionaryValue& parsed_json) {
177 web_resource_service_->OnWebResourceUnpacked(parsed_json); 92 web_resource_service_->Unpack(parsed_json);
178 Cleanup(); 93 Cleanup();
179 } 94 }
180 95
181 void OnUnpackWebResourceFailed(const std::string& error_message) { 96 void OnUnpackWebResourceFailed(const std::string& error_message) {
182 web_resource_service_->EndFetch(); 97 LOG(ERROR) << error_message;
183 Cleanup(); 98 Cleanup();
184 } 99 }
185 100
186 // Release reference and set got_response_. 101 // Release reference and set got_response_.
187 void Cleanup() { 102 void Cleanup() {
188 if (got_response_) 103 DCHECK(!got_response_);
189 return; 104 got_response_ = true;
190 105
191 got_response_ = true; 106 web_resource_service_->EndFetch();
192 Release(); 107 Release();
193 } 108 }
194 109
195 void StartProcessOnIOThread(BrowserThread::ID thread_id) { 110 void StartProcessOnIOThread(BrowserThread::ID thread_id,
111 const std::string& json_data) {
196 UtilityProcessHost* host = new UtilityProcessHost(this, thread_id); 112 UtilityProcessHost* host = new UtilityProcessHost(this, thread_id);
197 // TODO(mrc): get proper file path when we start using web resources 113 // TODO(mrc): get proper file path when we start using web resources
198 // that need to be unpacked. 114 // that need to be unpacked.
199 host->Send(new ChromeUtilityMsg_UnpackWebResource(json_data_)); 115 host->Send(new ChromeUtilityMsg_UnpackWebResource(json_data));
200 } 116 }
201 117
202 scoped_refptr<WebResourceService> web_resource_service_; 118 scoped_refptr<WebResourceService> web_resource_service_;
203 119
204 // Holds raw JSON string. 120 // Owned by the global browser process.
205 std::string json_data_; 121 ResourceDispatcherHost* resource_dispatcher_host_;
206 122
207 // True if we got a response from the utility process and have cleaned up 123 // True if we got a response from the utility process and have cleaned up
208 // already. 124 // already.
209 bool got_response_; 125 bool got_response_;
210 }; 126 };
211 127
212 WebResourceService::WebResourceService( 128 WebResourceService::WebResourceService(
213 PrefService* prefs, 129 PrefService* prefs,
214 const char* web_resource_server, 130 const char* web_resource_server,
215 bool apply_locale_to_url, 131 bool apply_locale_to_url,
216 int notification_type,
217 const char* last_update_time_pref_name, 132 const char* last_update_time_pref_name,
218 int start_fetch_delay, 133 int start_fetch_delay_ms,
219 int cache_update_delay) 134 int cache_update_delay_ms)
220 : prefs_(prefs), 135 : prefs_(prefs),
221 ALLOW_THIS_IN_INITIALIZER_LIST(service_factory_(this)), 136 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
222 in_fetch_(false), 137 in_fetch_(false),
223 web_resource_server_(web_resource_server), 138 web_resource_server_(web_resource_server),
224 apply_locale_to_url_(apply_locale_to_url), 139 apply_locale_to_url_(apply_locale_to_url),
225 notification_type_(notification_type),
226 last_update_time_pref_name_(last_update_time_pref_name), 140 last_update_time_pref_name_(last_update_time_pref_name),
227 start_fetch_delay_(start_fetch_delay), 141 start_fetch_delay_ms_(start_fetch_delay_ms),
228 cache_update_delay_(cache_update_delay), 142 cache_update_delay_ms_(cache_update_delay_ms) {
229 web_resource_update_scheduled_(false) {
230 DCHECK(prefs); 143 DCHECK(prefs);
231 prefs_->RegisterStringPref(last_update_time_pref_name,
232 "0",
233 PrefService::UNSYNCABLE_PREF);
234 resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host();
235 web_resource_fetcher_.reset(new WebResourceFetcher(this));
236 } 144 }
237 145
238 WebResourceService::~WebResourceService() { } 146 WebResourceService::~WebResourceService() { }
239 147
240 void WebResourceService::PostNotification(int64 delay_ms) { 148 // static
241 if (web_resource_update_scheduled_) 149 void WebResourceService::RegisterLastUpdateTimePref(PrefService* prefs,
242 return; 150 const char* pref_name) {
243 if (delay_ms > 0) { 151 prefs->RegisterStringPref(pref_name, "0", PrefService::UNSYNCABLE_PREF);
244 web_resource_update_scheduled_ = true;
245 MessageLoop::current()->PostDelayedTask(FROM_HERE,
246 service_factory_.NewRunnableMethod(
247 &WebResourceService::WebResourceStateChange), delay_ms);
248 } else if (delay_ms == 0) {
249 WebResourceStateChange();
250 }
251 } 152 }
252 153
253 void WebResourceService::EndFetch() { 154 void WebResourceService::EndFetch() {
254 in_fetch_ = false; 155 in_fetch_ = false;
255 } 156 }
256 157
257 void WebResourceService::OnWebResourceUnpacked( 158 bool WebResourceService::StartAfterDelay(bool only_if_necessary) {
258 const DictionaryValue& parsed_json) { 159 int64 delay = start_fetch_delay_ms_;
259 Unpack(parsed_json);
260 EndFetch();
261 }
262
263 void WebResourceService::WebResourceStateChange() {
264 web_resource_update_scheduled_ = false;
265 if (notification_type_ == chrome::NOTIFICATION_CHROME_END)
266 return;
267 content::NotificationService* service =
268 content::NotificationService::current();
269 service->Notify(notification_type_,
270 content::Source<WebResourceService>(this),
271 content::NotificationService::NoDetails());
272 }
273
274 void WebResourceService::StartAfterDelay() {
275 int64 delay = start_fetch_delay_;
276 // Check whether we have ever put a value in the web resource cache; 160 // Check whether we have ever put a value in the web resource cache;
277 // if so, pull it out and see if it's time to update again. 161 // if so, pull it out and see if it's time to update again.
278 if (prefs_->HasPrefPath(last_update_time_pref_name_)) { 162 if (prefs_->HasPrefPath(last_update_time_pref_name_)) {
279 std::string last_update_pref = 163 std::string last_update_pref =
280 prefs_->GetString(last_update_time_pref_name_); 164 prefs_->GetString(last_update_time_pref_name_);
281 if (!last_update_pref.empty()) { 165 if (!last_update_pref.empty()) {
282 double last_update_value; 166 double last_update_value;
283 base::StringToDouble(last_update_pref, &last_update_value); 167 base::StringToDouble(last_update_pref, &last_update_value);
284 int64 ms_until_update = cache_update_delay_ - 168 int64 ms_until_update = cache_update_delay_ms_ -
285 static_cast<int64>((base::Time::Now() - base::Time::FromDoubleT( 169 static_cast<int64>((base::Time::Now() - base::Time::FromDoubleT(
286 last_update_value)).InMilliseconds()); 170 last_update_value)).InMilliseconds());
287 delay = ms_until_update > cache_update_delay_ ? 171 // Wait at least |start_fetch_delay_ms_|.
288 cache_update_delay_ : (ms_until_update < start_fetch_delay_ ? 172 if (ms_until_update > start_fetch_delay_ms_)
289 start_fetch_delay_ : ms_until_update); 173 delay = ms_until_update;
174 else if (only_if_necessary)
175 return false;
290 } 176 }
291 } 177 }
292 // Start fetch and wait for UpdateResourceCache. 178 // Start fetch and wait for UpdateResourceCache.
293 web_resource_fetcher_->StartAfterDelay(delay); 179 ScheduleFetch(delay);
180 return true;
294 } 181 }
295 182
296 void WebResourceService::UpdateResourceCache(const std::string& json_data) { 183 // Delay initial load of resource data into cache so as not to interfere
297 UnpackerClient* client = new UnpackerClient(this, json_data); 184 // with startup time.
298 client->Start(); 185 void WebResourceService::ScheduleFetch(int64 delay_ms) {
186 MessageLoop::current()->PostDelayedTask(
187 FROM_HERE,
188 base::Bind(&WebResourceService::StartFetch,
189 weak_ptr_factory_.GetWeakPtr()),
190 delay_ms);
191 }
192
193 // Initializes the fetching of data from the resource server. Data
194 // load calls OnURLFetchComplete.
195 void WebResourceService::StartFetch() {
196 // First, put our next cache load on the MessageLoop.
197 ScheduleFetch(cache_update_delay_ms_);
299 198
300 // Set cache update time in preferences. 199 // Set cache update time in preferences.
301 prefs_->SetString(last_update_time_pref_name_, 200 prefs_->SetString(last_update_time_pref_name_,
302 base::DoubleToString(base::Time::Now().ToDoubleT())); 201 base::DoubleToString(base::Time::Now().ToDoubleT()));
202
203 // If we are still fetching data, exit.
204 if (in_fetch_)
205 return;
206 in_fetch_ = true;
207
208 // Balanced in OnURLFetchComplete.
209 AddRef();
210
211 std::string web_resource_server = web_resource_server_;
212 if (apply_locale_to_url_) {
213 std::string locale = g_browser_process->GetApplicationLocale();
214 web_resource_server.append(locale);
215 }
216
217 url_fetcher_.reset(content::URLFetcher::Create(
218 GURL(web_resource_server), content::URLFetcher::GET, this));
219 // Do not let url fetcher affect existing state in system context
220 // (by setting cookies, for example).
221 url_fetcher_->SetLoadFlags(net::LOAD_DISABLE_CACHE |
222 net::LOAD_DO_NOT_SAVE_COOKIES);
223 net::URLRequestContextGetter* url_request_context_getter =
224 g_browser_process->system_request_context();
225 url_fetcher_->SetRequestContext(url_request_context_getter);
226 url_fetcher_->Start();
303 } 227 }
228
229 void WebResourceService::OnURLFetchComplete(const content::URLFetcher* source) {
230 // Delete the URLFetcher when this function exits.
231 scoped_ptr<content::URLFetcher> clean_up_fetcher(url_fetcher_.release());
232
233 // Don't parse data if attempt to download was unsuccessful.
234 // Stop loading new web resource data, and silently exit.
235 if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200))
236 return;
237
238 std::string data;
239 source->GetResponseAsString(&data);
240
241 // UnpackerClient releases itself.
242 UnpackerClient* client = new UnpackerClient(this);
243 client->Start(data);
244
245 Release();
246 }
OLDNEW
« no previous file with comments | « chrome/browser/web_resource/web_resource_service.h ('k') | chrome/chrome_browser.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698