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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/web_resource/json_asynchronous_unpacker.h" 6 7 #include "base/command_line.h" 8 #include "chrome/browser/web_resource/web_resource_service.h" 9 #include "chrome/common/chrome_switches.h" 10 #include "chrome/common/chrome_utility_messages.h" 11 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/utility_process_host.h" 13 #include "content/public/browser/utility_process_host_client.h" 14 15 using content::BrowserThread; 16 using content::UtilityProcessHost; 17 using content::UtilityProcessHostClient; 18 19 // This class coordinates a web resource unpack and parse task which is run in 20 // a separate process. Results are sent back to this class and routed to 21 // the WebResourceService. 22 class JSONAsynchronousUnpackerImpl 23 : public UtilityProcessHostClient, 24 public JSONAsynchronousUnpacker { 25 public: 26 explicit JSONAsynchronousUnpackerImpl( 27 JSONAsynchronousUnpackerDelegate* delegate) 28 : JSONAsynchronousUnpacker(delegate), 29 got_response_(false) { 30 } 31 32 virtual void Start(const std::string& json_data) OVERRIDE { 33 AddRef(); // balanced in Cleanup. 34 35 BrowserThread::ID thread_id; 36 CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id)); 37 BrowserThread::PostTask( 38 BrowserThread::IO, FROM_HERE, 39 base::Bind( 40 &JSONAsynchronousUnpackerImpl::StartProcessOnIOThread, 41 this, thread_id, json_data)); 42 } 43 44 private: 45 virtual ~JSONAsynchronousUnpackerImpl() {} 46 47 // UtilityProcessHostClient. 48 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 49 bool handled = true; 50 IPC_BEGIN_MESSAGE_MAP(JSONAsynchronousUnpackerImpl, message) 51 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Succeeded, 52 OnUnpackWebResourceSucceeded) 53 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Failed, 54 OnUnpackWebResourceFailed) 55 IPC_MESSAGE_UNHANDLED(handled = false) 56 IPC_END_MESSAGE_MAP() 57 return handled; 58 } 59 60 virtual void OnProcessCrashed(int exit_code) OVERRIDE { 61 if (got_response_) 62 return; 63 64 OnUnpackWebResourceFailed( 65 "Utility process crashed while trying to retrieve web resources."); 66 } 67 68 void OnUnpackWebResourceSucceeded( 69 const base::DictionaryValue& parsed_json) { 70 if (delegate_) 71 delegate_->OnUnpackFinished(parsed_json); 72 Cleanup(); 73 } 74 75 void OnUnpackWebResourceFailed(const std::string& error_message) { 76 if (delegate_) 77 delegate_->OnUnpackError(error_message); 78 Cleanup(); 79 } 80 81 // Release reference and set got_response_. 82 void Cleanup() { 83 DCHECK(!got_response_); 84 got_response_ = true; 85 Release(); 86 } 87 88 void StartProcessOnIOThread(BrowserThread::ID thread_id, 89 const std::string& json_data) { 90 UtilityProcessHost* host = UtilityProcessHost::Create( 91 this, BrowserThread::GetMessageLoopProxyForThread(thread_id).get()); 92 // TODO(mrc): get proper file path when we start using web resources 93 // that need to be unpacked. 94 host->Send(new ChromeUtilityMsg_UnpackWebResource(json_data)); 95 } 96 97 // True if we got a response from the utility process and have cleaned up 98 // already. 99 bool got_response_; 100 }; 101 102 JSONAsynchronousUnpacker* JSONAsynchronousUnpacker::Create( 103 JSONAsynchronousUnpackerDelegate* delegate) { 104 return new JSONAsynchronousUnpackerImpl(delegate); 105 } 106 107