json_asynchronous_unpacker.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "chrome/common/web_resource/web_resource_unpacker.h" 12#include "content/public/browser/browser_thread.h" 13#include "content/public/browser/resource_dispatcher_host.h" 14#include "content/public/browser/utility_process_host.h" 15#include "content/public/browser/utility_process_host_client.h" 16 17using content::BrowserThread; 18using content::UtilityProcessHost; 19using content::UtilityProcessHostClient; 20 21// This class coordinates a web resource unpack and parse task which is run in 22// a separate process. Results are sent back to this class and routed to 23// the WebResourceService. 24class JSONAsynchronousUnpackerImpl 25 : public UtilityProcessHostClient, 26 public JSONAsynchronousUnpacker { 27 public: 28 explicit JSONAsynchronousUnpackerImpl( 29 JSONAsynchronousUnpackerDelegate* delegate) 30 : JSONAsynchronousUnpacker(delegate), 31 got_response_(false) { 32 } 33 34 void Start(const std::string& json_data) { 35 AddRef(); // balanced in Cleanup. 36 37 // TODO(willchan): Look for a better signal of whether we're in a unit test 38 // or not. Using |ResourceDispatcherHost::Get()| for this is pretty lame. 39 // If we don't have a ResourceDispatcherHost, assume we're in a test and 40 // run the unpacker directly in-process. 41 bool use_utility_process = 42 content::ResourceDispatcherHost::Get() && 43 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess); 44 if (use_utility_process) { 45 BrowserThread::ID thread_id; 46 CHECK(BrowserThread::GetCurrentThreadIdentifier(&thread_id)); 47 BrowserThread::PostTask( 48 BrowserThread::IO, FROM_HERE, 49 base::Bind( 50 &JSONAsynchronousUnpackerImpl::StartProcessOnIOThread, 51 this, thread_id, json_data)); 52 } else { 53 WebResourceUnpacker unpacker(json_data); 54 if (unpacker.Run()) { 55 OnUnpackWebResourceSucceeded(*unpacker.parsed_json()); 56 } else { 57 OnUnpackWebResourceFailed(unpacker.error_message()); 58 } 59 } 60 } 61 62 private: 63 virtual ~JSONAsynchronousUnpackerImpl() {} 64 65 // UtilityProcessHostClient. 66 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { 67 bool handled = true; 68 IPC_BEGIN_MESSAGE_MAP(JSONAsynchronousUnpackerImpl, message) 69 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Succeeded, 70 OnUnpackWebResourceSucceeded) 71 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_UnpackWebResource_Failed, 72 OnUnpackWebResourceFailed) 73 IPC_MESSAGE_UNHANDLED(handled = false) 74 IPC_END_MESSAGE_MAP() 75 return handled; 76 } 77 78 virtual void OnProcessCrashed(int exit_code) OVERRIDE { 79 if (got_response_) 80 return; 81 82 OnUnpackWebResourceFailed( 83 "Utility process crashed while trying to retrieve web resources."); 84 } 85 86 void OnUnpackWebResourceSucceeded( 87 const DictionaryValue& parsed_json) { 88 if (delegate_) 89 delegate_->OnUnpackFinished(parsed_json); 90 Cleanup(); 91 } 92 93 void OnUnpackWebResourceFailed(const std::string& error_message) { 94 if (delegate_) 95 delegate_->OnUnpackError(error_message); 96 Cleanup(); 97 } 98 99 // Release reference and set got_response_. 100 void Cleanup() { 101 DCHECK(!got_response_); 102 got_response_ = true; 103 Release(); 104 } 105 106 void StartProcessOnIOThread(BrowserThread::ID thread_id, 107 const std::string& json_data) { 108 UtilityProcessHost* host = UtilityProcessHost::Create(this, thread_id); 109 host->EnableZygote(); 110 // TODO(mrc): get proper file path when we start using web resources 111 // that need to be unpacked. 112 host->Send(new ChromeUtilityMsg_UnpackWebResource(json_data)); 113 } 114 115 // True if we got a response from the utility process and have cleaned up 116 // already. 117 bool got_response_; 118}; 119 120JSONAsynchronousUnpacker* JSONAsynchronousUnpacker::Create( 121 JSONAsynchronousUnpackerDelegate* delegate) { 122 return new JSONAsynchronousUnpackerImpl(delegate); 123} 124 125