Index: chrome/browser/web_resource/json_asynchronous_unpacker.cc |
diff --git a/chrome/browser/web_resource/json_asynchronous_unpacker.cc b/chrome/browser/web_resource/json_asynchronous_unpacker.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f797a2f151d59a6171061f7d42037f84d470ef5c |
--- /dev/null |
+++ b/chrome/browser/web_resource/json_asynchronous_unpacker.cc |
@@ -0,0 +1,124 @@ |
+// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/web_resource/json_asynchronous_unpacker.h" |
+ |
+#include "base/command_line.h" |
+#include "chrome/browser/web_resource/web_resource_service.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "chrome/common/chrome_utility_messages.h" |
+#include "chrome/common/web_resource/web_resource_unpacker.h" |
+#include "content/public/browser/browser_thread.h" |
+#include "content/public/browser/resource_dispatcher_host.h" |
+#include "content/public/browser/utility_process_host.h" |
+#include "content/public/browser/utility_process_host_client.h" |
+ |
+using content::BrowserThread; |
+using content::UtilityProcessHost; |
+using content::UtilityProcessHostClient; |
+ |
+// This class coordinates a web resource unpack and parse task which is run in |
+// a separate process. Results are sent back to this class and routed to |
+// the WebResourceService. |
+class JSONAsynchronousUnpackerImpl |
+ : public UtilityProcessHostClient, |
+ public JSONAsynchronousUnpacker { |
+ public: |
+ explicit JSONAsynchronousUnpackerImpl( |
+ JSONAsynchronousUnpackerDelegate* delegate) |
+ : JSONAsynchronousUnpacker(delegate), |
+ got_response_(false) { |
+ } |
+ |
+ void Start(const std::string& json_data) { |
+ AddRef(); // balanced in Cleanup. |
+ |
+ // TODO(willchan): Look for a better signal of whether we're in a unit test |
+ // or not. Using |ResourceDispatcherHost::Get()| for this is pretty lame. |
+ // If we don't have a ResourceDispatcherHost, assume we're in a test and |
+ // run the unpacker directly in-process. |
+ bool use_utility_process = |
+ content::ResourceDispatcherHost::Get() && |
+ !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); |
+ if (use_utility_process) { |
+ BrowserThread::ID thread_id; |
+ CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id)); |
+ BrowserThread::PostTask( |
+ BrowserThread::IO, FROM_HERE, |
+ base::Bind( |
+ &JSONAsynchronousUnpackerImpl::StartProcessOnIOThread, |
+ this, thread_id, json_data)); |
+ } else { |
+ WebResourceUnpacker unpacker(json_data); |
+ if (unpacker.Run()) { |
+ OnUnpackWebResourceSucceeded(*unpacker.parsed_json()); |
+ } else { |
+ OnUnpackWebResourceFailed(unpacker.error_message()); |
+ } |
+ } |
+ } |
+ |
+ private: |
+ virtual ~JSONAsynchronousUnpackerImpl() {} |
+ |
+ // UtilityProcessHostClient. |
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
+ bool handled = true; |
+ IPC_BEGIN_MESSAGE_MAP(JSONAsynchronousUnpackerImpl, message) |
+ IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Succeeded, |
+ OnUnpackWebResourceSucceeded) |
+ IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Failed, |
+ OnUnpackWebResourceFailed) |
+ IPC_MESSAGE_UNHANDLED(handled = false) |
+ IPC_END_MESSAGE_MAP() |
+ return handled; |
+ } |
+ |
+ virtual void OnProcessCrashed(int exit_code) OVERRIDE { |
+ if (got_response_) |
+ return; |
+ |
+ OnUnpackWebResourceFailed( |
+ "Utility process crashed while trying to retrieve web resources."); |
+ } |
+ |
+ void OnUnpackWebResourceSucceeded( |
+ const DictionaryValue& parsed_json) { |
+ if (delegate_) |
+ delegate_->OnUnpackFinished(parsed_json); |
+ Cleanup(); |
+ } |
+ |
+ void OnUnpackWebResourceFailed(const std::string& error_message) { |
+ if (delegate_) |
+ delegate_->OnUnpackError(error_message); |
+ Cleanup(); |
+ } |
+ |
+ // Release reference and set got_response_. |
+ void Cleanup() { |
+ DCHECK(!got_response_); |
+ got_response_ = true; |
+ Release(); |
+ } |
+ |
+ void StartProcessOnIOThread(BrowserThread::ID thread_id, |
+ const std::string& json_data) { |
+ UtilityProcessHost* host = UtilityProcessHost::Create(this, thread_id); |
+ host->EnableZygote(); |
+ // TODO(mrc): get proper file path when we start using web resources |
+ // that need to be unpacked. |
+ host->Send(new ChromeUtilityMsg_UnpackWebResource(json_data)); |
+ } |
+ |
+ // True if we got a response from the utility process and have cleaned up |
+ // already. |
+ bool got_response_; |
+}; |
+ |
+JSONAsynchronousUnpacker* JSONAsynchronousUnpacker::Create( |
+ JSONAsynchronousUnpackerDelegate* delegate) { |
+ return new JSONAsynchronousUnpackerImpl(delegate); |
+} |
+ |