| 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 |