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 12using content::BrowserThread; 13 14ImageWriterUtilityClient::ImageWriterUtilityClient() 15 : message_loop_proxy_(base::MessageLoopProxy::current()) {} 16ImageWriterUtilityClient::~ImageWriterUtilityClient() {} 17 18void 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 38void 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 58void 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 74void 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 87void 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 103void ImageWriterUtilityClient::OnProcessCrashed(int exit_code) { 104 message_loop_proxy_->PostTask( 105 FROM_HERE, base::Bind(error_callback_, "Utility process crashed.")); 106} 107 108void ImageWriterUtilityClient::OnProcessLaunchFailed() { 109 message_loop_proxy_->PostTask( 110 FROM_HERE, base::Bind(error_callback_, "Process launch failed.")); 111} 112 113bool 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 129bool ImageWriterUtilityClient::Send(IPC::Message* msg) { 130 return utility_process_host_ && utility_process_host_->Send(msg); 131} 132 133void ImageWriterUtilityClient::OnWriteImageSucceeded() { 134 if (!success_callback_.is_null()) { 135 message_loop_proxy_->PostTask(FROM_HERE, success_callback_); 136 } 137} 138 139void ImageWriterUtilityClient::OnWriteImageCancelled() { 140 if (!cancel_callback_.is_null()) { 141 message_loop_proxy_->PostTask(FROM_HERE, cancel_callback_); 142 } 143} 144 145void 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 152void 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