OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/bind.h" |
8 #include "base/command_line.h" | |
9 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
10 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
11 #include "base/string_util.h" | 10 #include "base/string_util.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/google/google_util.h" | 15 #include "chrome/browser/google/google_util.h" |
17 #include "chrome/browser/prefs/pref_service.h" | 16 #include "chrome/browser/prefs/pref_service.h" |
18 #include "chrome/common/chrome_switches.h" | |
19 #include "chrome/common/chrome_utility_messages.h" | |
20 #include "chrome/common/web_resource/web_resource_unpacker.h" | |
21 #include "content/public/browser/browser_thread.h" | |
22 #include "content/public/browser/resource_dispatcher_host.h" | |
23 #include "content/public/browser/utility_process_host.h" | |
24 #include "content/public/browser/utility_process_host_client.h" | |
25 #include "googleurl/src/gurl.h" | 17 #include "googleurl/src/gurl.h" |
26 #include "net/base/load_flags.h" | 18 #include "net/base/load_flags.h" |
27 #include "net/url_request/url_fetcher.h" | 19 #include "net/url_request/url_fetcher.h" |
28 #include "net/url_request/url_request_status.h" | 20 #include "net/url_request/url_request_status.h" |
29 | 21 |
30 using content::BrowserThread; | |
31 using content::UtilityProcessHost; | |
32 using content::UtilityProcessHostClient; | |
33 | |
34 // This class coordinates a web resource unpack and parse task which is run in | |
35 // a separate process. Results are sent back to this class and routed to | |
36 // the WebResourceService. | |
37 class WebResourceService::UnpackerClient : public UtilityProcessHostClient { | |
38 public: | |
39 explicit UnpackerClient(WebResourceService* web_resource_service) | |
40 : web_resource_service_(web_resource_service), | |
41 got_response_(false) { | |
42 } | |
43 | |
44 void Start(const std::string& json_data) { | |
45 AddRef(); // balanced in Cleanup. | |
46 | |
47 // TODO(willchan): Look for a better signal of whether we're in a unit test | |
48 // or not. Using |ResourceDispatcherHost::Get()| for this is pretty lame. | |
49 // If we don't have a ResourceDispatcherHost, assume we're in a test and | |
50 // run the unpacker directly in-process. | |
51 bool use_utility_process = | |
52 content::ResourceDispatcherHost::Get() && | |
53 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); | |
54 if (use_utility_process) { | |
55 BrowserThread::ID thread_id; | |
56 CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id)); | |
57 BrowserThread::PostTask( | |
58 BrowserThread::IO, FROM_HERE, | |
59 base::Bind(&UnpackerClient::StartProcessOnIOThread, | |
60 this, thread_id, json_data)); | |
61 } else { | |
62 WebResourceUnpacker unpacker(json_data); | |
63 if (unpacker.Run()) { | |
64 OnUnpackWebResourceSucceeded(*unpacker.parsed_json()); | |
65 } else { | |
66 OnUnpackWebResourceFailed(unpacker.error_message()); | |
67 } | |
68 } | |
69 } | |
70 | |
71 private: | |
72 virtual ~UnpackerClient() {} | |
73 | |
74 // UtilityProcessHostClient | |
75 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { | |
76 bool handled = true; | |
77 IPC_BEGIN_MESSAGE_MAP(WebResourceService::UnpackerClient, message) | |
78 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Succeeded, | |
79 OnUnpackWebResourceSucceeded) | |
80 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Failed, | |
81 OnUnpackWebResourceFailed) | |
82 IPC_MESSAGE_UNHANDLED(handled = false) | |
83 IPC_END_MESSAGE_MAP() | |
84 return handled; | |
85 } | |
86 | |
87 virtual void OnProcessCrashed(int exit_code) OVERRIDE { | |
88 if (got_response_) | |
89 return; | |
90 | |
91 OnUnpackWebResourceFailed( | |
92 "Utility process crashed while trying to retrieve web resources."); | |
93 } | |
94 | |
95 void OnUnpackWebResourceSucceeded( | |
96 const DictionaryValue& parsed_json) { | |
97 web_resource_service_->Unpack(parsed_json); | |
98 Cleanup(); | |
99 } | |
100 | |
101 void OnUnpackWebResourceFailed(const std::string& error_message) { | |
102 LOG(ERROR) << error_message; | |
103 Cleanup(); | |
104 } | |
105 | |
106 // Release reference and set got_response_. | |
107 void Cleanup() { | |
108 DCHECK(!got_response_); | |
109 got_response_ = true; | |
110 | |
111 web_resource_service_->EndFetch(); | |
112 Release(); | |
113 } | |
114 | |
115 void StartProcessOnIOThread(BrowserThread::ID thread_id, | |
116 const std::string& json_data) { | |
117 UtilityProcessHost* host = UtilityProcessHost::Create(this, thread_id); | |
118 host->EnableZygote(); | |
119 // TODO(mrc): get proper file path when we start using web resources | |
120 // that need to be unpacked. | |
121 host->Send(new ChromeUtilityMsg_UnpackWebResource(json_data)); | |
122 } | |
123 | |
124 scoped_refptr<WebResourceService> web_resource_service_; | |
125 | |
126 // True if we got a response from the utility process and have cleaned up | |
127 // already. | |
128 bool got_response_; | |
129 }; | |
130 | |
131 WebResourceService::WebResourceService( | 22 WebResourceService::WebResourceService( |
132 PrefService* prefs, | 23 PrefService* prefs, |
133 const GURL& web_resource_server, | 24 const GURL& web_resource_server, |
134 bool apply_locale_to_url, | 25 bool apply_locale_to_url, |
135 const char* last_update_time_pref_name, | 26 const char* last_update_time_pref_name, |
136 int start_fetch_delay_ms, | 27 int start_fetch_delay_ms, |
137 int cache_update_delay_ms) | 28 int cache_update_delay_ms) |
138 : prefs_(prefs), | 29 : prefs_(prefs), |
139 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | 30 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
31 json_unpacker_(NULL), | |
140 in_fetch_(false), | 32 in_fetch_(false), |
141 web_resource_server_(web_resource_server), | 33 web_resource_server_(web_resource_server), |
142 apply_locale_to_url_(apply_locale_to_url), | 34 apply_locale_to_url_(apply_locale_to_url), |
143 last_update_time_pref_name_(last_update_time_pref_name), | 35 last_update_time_pref_name_(last_update_time_pref_name), |
144 start_fetch_delay_ms_(start_fetch_delay_ms), | 36 start_fetch_delay_ms_(start_fetch_delay_ms), |
145 cache_update_delay_ms_(cache_update_delay_ms) { | 37 cache_update_delay_ms_(cache_update_delay_ms) { |
146 DCHECK(prefs); | 38 DCHECK(prefs); |
147 } | 39 } |
148 | 40 |
149 WebResourceService::~WebResourceService() { } | 41 WebResourceService::~WebResourceService() { |
42 if (in_fetch_) | |
43 EndFetch(); | |
44 } | |
45 | |
46 void WebResourceService::OnUnpackFinished(const DictionaryValue& parsed_json) { | |
Miranda Callahan
2012/07/09 14:24:30
Having these in both the WRS and the derived PRS i
noyau (Ping after 24h)
2012/07/09 15:23:57
EndFetch IMHO should stay private to the class. It
| |
47 EndFetch(); | |
48 } | |
49 | |
50 void WebResourceService::OnUnpackError(const std::string& error_message) { | |
51 EndFetch(); | |
52 } | |
150 | 53 |
151 void WebResourceService::EndFetch() { | 54 void WebResourceService::EndFetch() { |
55 if (json_unpacker_) { | |
56 json_unpacker_->ClearDelegate(); | |
57 json_unpacker_ = NULL; | |
58 } | |
152 in_fetch_ = false; | 59 in_fetch_ = false; |
153 } | 60 } |
154 | 61 |
155 void WebResourceService::StartAfterDelay() { | 62 void WebResourceService::StartAfterDelay() { |
156 int64 delay = start_fetch_delay_ms_; | 63 int64 delay = start_fetch_delay_ms_; |
157 // Check whether we have ever put a value in the web resource cache; | 64 // Check whether we have ever put a value in the web resource cache; |
158 // if so, pull it out and see if it's time to update again. | 65 // if so, pull it out and see if it's time to update again. |
159 if (prefs_->HasPrefPath(last_update_time_pref_name_)) { | 66 if (prefs_->HasPrefPath(last_update_time_pref_name_)) { |
160 std::string last_update_pref = | 67 std::string last_update_pref = |
161 prefs_->GetString(last_update_time_pref_name_); | 68 prefs_->GetString(last_update_time_pref_name_); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
222 | 129 |
223 void WebResourceService::OnURLFetchComplete(const net::URLFetcher* source) { | 130 void WebResourceService::OnURLFetchComplete(const net::URLFetcher* source) { |
224 // Delete the URLFetcher when this function exits. | 131 // Delete the URLFetcher when this function exits. |
225 scoped_ptr<net::URLFetcher> clean_up_fetcher(url_fetcher_.release()); | 132 scoped_ptr<net::URLFetcher> clean_up_fetcher(url_fetcher_.release()); |
226 | 133 |
227 if (source->GetStatus().is_success() && source->GetResponseCode() == 200) { | 134 if (source->GetStatus().is_success() && source->GetResponseCode() == 200) { |
228 std::string data; | 135 std::string data; |
229 source->GetResponseAsString(&data); | 136 source->GetResponseAsString(&data); |
230 | 137 |
231 // UnpackerClient calls EndFetch and releases itself on completion. | 138 // UnpackerClient calls EndFetch and releases itself on completion. |
232 UnpackerClient* client = new UnpackerClient(this); | 139 json_unpacker_ = JSONAsynchronousUnpacker::Create(this); |
233 client->Start(data); | 140 json_unpacker_->Start(data); |
234 } else { | 141 } else { |
235 // Don't parse data if attempt to download was unsuccessful. | 142 // Don't parse data if attempt to download was unsuccessful. |
236 // Stop loading new web resource data, and silently exit. | 143 // Stop loading new web resource data, and silently exit. |
237 // We do not call UnpackerClient, so we need to call EndFetch ourselves. | 144 // We do not call UnpackerClient, so we need to call EndFetch ourselves. |
238 EndFetch(); | 145 EndFetch(); |
239 } | 146 } |
240 | 147 |
241 Release(); | 148 Release(); |
242 } | 149 } |
OLD | NEW |