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/chrome_utility_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 utility_process_host_->DisableSandbox(); 101 } 102 } 103 104 void ImageWriterUtilityClient::OnProcessCrashed(int exit_code) { 105 message_loop_proxy_->PostTask( 106 FROM_HERE, base::Bind(error_callback_, "Utility process crashed.")); 107 } 108 109 void ImageWriterUtilityClient::OnProcessLaunchFailed() { 110 message_loop_proxy_->PostTask( 111 FROM_HERE, base::Bind(error_callback_, "Process launch failed.")); 112 } 113 114 bool ImageWriterUtilityClient::OnMessageReceived(const IPC::Message& message) { 115 bool handled = true; 116 IPC_BEGIN_MESSAGE_MAP(ImageWriterUtilityClient, message) 117 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ImageWriter_Succeeded, 118 OnWriteImageSucceeded) 119 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ImageWriter_Cancelled, 120 OnWriteImageCancelled) 121 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ImageWriter_Failed, 122 OnWriteImageFailed) 123 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ImageWriter_Progress, 124 OnWriteImageProgress) 125 IPC_MESSAGE_UNHANDLED(handled = false) 126 IPC_END_MESSAGE_MAP() 127 return handled; 128 } 129 130 bool ImageWriterUtilityClient::Send(IPC::Message* msg) { 131 return utility_process_host_ && utility_process_host_->Send(msg); 132 } 133 134 void ImageWriterUtilityClient::OnWriteImageSucceeded() { 135 if (!success_callback_.is_null()) { 136 message_loop_proxy_->PostTask(FROM_HERE, success_callback_); 137 } 138 } 139 140 void ImageWriterUtilityClient::OnWriteImageCancelled() { 141 if (!cancel_callback_.is_null()) { 142 message_loop_proxy_->PostTask(FROM_HERE, cancel_callback_); 143 } 144 } 145 146 void ImageWriterUtilityClient::OnWriteImageFailed(const std::string& message) { 147 if (!error_callback_.is_null()) { 148 message_loop_proxy_->PostTask(FROM_HERE, 149 base::Bind(error_callback_, message)); 150 } 151 } 152 153 void ImageWriterUtilityClient::OnWriteImageProgress(int64 progress) { 154 if (!progress_callback_.is_null()) { 155 message_loop_proxy_->PostTask(FROM_HERE, 156 base::Bind(progress_callback_, progress)); 157 } 158 } 159