1 // Copyright 2014 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 "base/bind.h" 6 #include "base/message_loop/message_loop.h" 7 #include "chrome/browser/browser_process.h" 8 #include "chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.h" 9 #include "chrome/common/extensions/chrome_utility_extensions_messages.h" 10 #include "content/public/browser/browser_thread.h" 11 12 using content::BrowserThread; 13 14 ImageWriterUtilityClient::ImageWriterUtilityClient() 15 : message_loop_proxy_(base::MessageLoopProxy::current()) {} 16 ImageWriterUtilityClient::~ImageWriterUtilityClient() {} 17 18 void ImageWriterUtilityClient::Write(const ProgressCallback& progress_callback, 19 const SuccessCallback& success_callback, 20 const ErrorCallback& error_callback, 21 const base::FilePath& source, 22 const base::FilePath& target) { 23 DCHECK_CURRENTLY_ON(BrowserThread::IO); 24 25 StartHost(); 26 27 progress_callback_ = progress_callback; 28 success_callback_ = success_callback; 29 error_callback_ = error_callback; 30 31 if (!Send(new ChromeUtilityMsg_ImageWriter_Write(source, target))) { 32 DLOG(ERROR) << "Unable to send Write message to Utility Process."; 33 message_loop_proxy_->PostTask( 34 FROM_HERE, base::Bind(error_callback_, "IPC communication failed")); 35 } 36 } 37 38 void ImageWriterUtilityClient::Verify(const ProgressCallback& progress_callback, 39 const SuccessCallback& success_callback, 40 const ErrorCallback& error_callback, 41 const base::FilePath& source, 42 const base::FilePath& target) { 43 DCHECK_CURRENTLY_ON(BrowserThread::IO); 44 45 StartHost(); 46 47 progress_callback_ = progress_callback; 48 success_callback_ = success_callback; 49 error_callback_ = error_callback; 50 51 if (!Send(new ChromeUtilityMsg_ImageWriter_Verify(source, target))) { 52 DLOG(ERROR) << "Unable to send Verify message to Utility Process."; 53 message_loop_proxy_->PostTask( 54 FROM_HERE, base::Bind(error_callback_, "IPC communication failed")); 55 } 56 } 57 58 void ImageWriterUtilityClient::Cancel(const CancelCallback& cancel_callback) { 59 DCHECK_CURRENTLY_ON(BrowserThread::IO); 60 61 if (!utility_process_host_) { 62 // If we haven't connected, there is nothing to cancel. 63 message_loop_proxy_->PostTask(FROM_HERE, cancel_callback); 64 return; 65 } 66 67 cancel_callback_ = cancel_callback; 68 69 if (!Send(new ChromeUtilityMsg_ImageWriter_Cancel())) { 70 DLOG(ERROR) << "Unable to send Cancel message to Utility Process."; 71 } 72 } 73 74 void ImageWriterUtilityClient::Shutdown() { 75 if (utility_process_host_ && 76 Send(new ChromeUtilityMsg_ImageWriter_Cancel())) { 77 utility_process_host_->EndBatchMode(); 78 } 79 80 // Clear handlers to not hold any reference to the caller. 81 success_callback_ = base::Closure(); 82 progress_callback_ = base::Callback<void(int64)>(); 83 error_callback_ = base::Callback<void(const std::string&)>(); 84 cancel_callback_ = base::Closure(); 85 } 86 87 void ImageWriterUtilityClient::StartHost() { 88 if (!utility_process_host_) { 89 scoped_refptr<base::SequencedTaskRunner> task_runner = 90 base::MessageLoop::current()->message_loop_proxy(); 91 utility_process_host_ = content::UtilityProcessHost::Create( 92 this, task_runner.get())->AsWeakPtr(); 93 94 #if defined(OS_WIN) 95 utility_process_host_->ElevatePrivileges(); 96 #else 97 utility_process_host_->DisableSandbox(); 98 #endif 99 utility_process_host_->StartBatchMode(); 100 } 101 } 102 103 void ImageWriterUtilityClient::OnProcessCrashed(int exit_code) { 104 message_loop_proxy_->PostTask( 105 FROM_HERE, base::Bind(error_callback_, "Utility process crashed.")); 106 } 107 108 void ImageWriterUtilityClient::OnProcessLaunchFailed() { 109 message_loop_proxy_->PostTask( 110 FROM_HERE, base::Bind(error_callback_, "Process launch failed.")); 111 } 112 113 bool ImageWriterUtilityClient::OnMessageReceived(const IPC::Message& message) { 114 bool handled = true; 115 IPC_BEGIN_MESSAGE_MAP(ImageWriterUtilityClient, message) 116 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ImageWriter_Succeeded, 117 OnWriteImageSucceeded) 118 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ImageWriter_Cancelled, 119 OnWriteImageCancelled) 120 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ImageWriter_Failed, 121 OnWriteImageFailed) 122 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ImageWriter_Progress, 123 OnWriteImageProgress) 124 IPC_MESSAGE_UNHANDLED(handled = false) 125 IPC_END_MESSAGE_MAP() 126 return handled; 127 } 128 129 bool ImageWriterUtilityClient::Send(IPC::Message* msg) { 130 return utility_process_host_ && utility_process_host_->Send(msg); 131 } 132 133 void ImageWriterUtilityClient::OnWriteImageSucceeded() { 134 if (!success_callback_.is_null()) { 135 message_loop_proxy_->PostTask(FROM_HERE, success_callback_); 136 } 137 } 138 139 void ImageWriterUtilityClient::OnWriteImageCancelled() { 140 if (!cancel_callback_.is_null()) { 141 message_loop_proxy_->PostTask(FROM_HERE, cancel_callback_); 142 } 143 } 144 145 void ImageWriterUtilityClient::OnWriteImageFailed(const std::string& message) { 146 if (!error_callback_.is_null()) { 147 message_loop_proxy_->PostTask(FROM_HERE, 148 base::Bind(error_callback_, message)); 149 } 150 } 151 152 void ImageWriterUtilityClient::OnWriteImageProgress(int64 progress) { 153 if (!progress_callback_.is_null()) { 154 message_loop_proxy_->PostTask(FROM_HERE, 155 base::Bind(progress_callback_, progress)); 156 } 157 } 158