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) { |
| 47 Unpack(parsed_json); |
| 48 EndFetch(); |
| 49 } |
| 50 |
| 51 void WebResourceService::OnUnpackError(const std::string& error_message) { |
| 52 LOG(ERROR) << error_message; |
| 53 EndFetch(); |
| 54 } |
150 | 55 |
151 void WebResourceService::EndFetch() { | 56 void WebResourceService::EndFetch() { |
| 57 if (json_unpacker_) { |
| 58 json_unpacker_->ClearDelegate(); |
| 59 json_unpacker_ = NULL; |
| 60 } |
152 in_fetch_ = false; | 61 in_fetch_ = false; |
153 } | 62 } |
154 | 63 |
155 void WebResourceService::StartAfterDelay() { | 64 void WebResourceService::StartAfterDelay() { |
156 int64 delay = start_fetch_delay_ms_; | 65 int64 delay = start_fetch_delay_ms_; |
157 // Check whether we have ever put a value in the web resource cache; | 66 // 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. | 67 // if so, pull it out and see if it's time to update again. |
159 if (prefs_->HasPrefPath(last_update_time_pref_name_)) { | 68 if (prefs_->HasPrefPath(last_update_time_pref_name_)) { |
160 std::string last_update_pref = | 69 std::string last_update_pref = |
161 prefs_->GetString(last_update_time_pref_name_); | 70 prefs_->GetString(last_update_time_pref_name_); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 | 131 |
223 void WebResourceService::OnURLFetchComplete(const net::URLFetcher* source) { | 132 void WebResourceService::OnURLFetchComplete(const net::URLFetcher* source) { |
224 // Delete the URLFetcher when this function exits. | 133 // Delete the URLFetcher when this function exits. |
225 scoped_ptr<net::URLFetcher> clean_up_fetcher(url_fetcher_.release()); | 134 scoped_ptr<net::URLFetcher> clean_up_fetcher(url_fetcher_.release()); |
226 | 135 |
227 if (source->GetStatus().is_success() && source->GetResponseCode() == 200) { | 136 if (source->GetStatus().is_success() && source->GetResponseCode() == 200) { |
228 std::string data; | 137 std::string data; |
229 source->GetResponseAsString(&data); | 138 source->GetResponseAsString(&data); |
230 | 139 |
231 // UnpackerClient calls EndFetch and releases itself on completion. | 140 // UnpackerClient calls EndFetch and releases itself on completion. |
232 UnpackerClient* client = new UnpackerClient(this); | 141 json_unpacker_ = JSONAsynchronousUnpacker::Create(this); |
233 client->Start(data); | 142 json_unpacker_->Start(data); |
234 } else { | 143 } else { |
235 // Don't parse data if attempt to download was unsuccessful. | 144 // Don't parse data if attempt to download was unsuccessful. |
236 // Stop loading new web resource data, and silently exit. | 145 // Stop loading new web resource data, and silently exit. |
237 // We do not call UnpackerClient, so we need to call EndFetch ourselves. | 146 // We do not call UnpackerClient, so we need to call EndFetch ourselves. |
238 EndFetch(); | 147 EndFetch(); |
239 } | 148 } |
240 | 149 |
241 Release(); | 150 Release(); |
242 } | 151 } |
OLD | NEW |