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 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 utility_process_host_->DisableSandbox(); 101 } 102} 103 104void ImageWriterUtilityClient::OnProcessCrashed(int exit_code) { 105 message_loop_proxy_->PostTask( 106 FROM_HERE, base::Bind(error_callback_, "Utility process crashed.")); 107} 108 109void ImageWriterUtilityClient::OnProcessLaunchFailed() { 110 message_loop_proxy_->PostTask( 111 FROM_HERE, base::Bind(error_callback_, "Process launch failed.")); 112} 113 114bool 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 130bool ImageWriterUtilityClient::Send(IPC::Message* msg) { 131 return utility_process_host_ && utility_process_host_->Send(msg); 132} 133 134void ImageWriterUtilityClient::OnWriteImageSucceeded() { 135 if (!success_callback_.is_null()) { 136 message_loop_proxy_->PostTask(FROM_HERE, success_callback_); 137 } 138} 139 140void ImageWriterUtilityClient::OnWriteImageCancelled() { 141 if (!cancel_callback_.is_null()) { 142 message_loop_proxy_->PostTask(FROM_HERE, cancel_callback_); 143 } 144} 145 146void 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 153void 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