| OLD | NEW |
| (Empty) |
| 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/files/file_path.h" | |
| 6 #include "chrome/common/chrome_utility_messages.h" | |
| 7 #include "chrome/utility/image_writer/error_messages.h" | |
| 8 #include "chrome/utility/image_writer/image_writer_handler.h" | |
| 9 #include "content/public/utility/utility_thread.h" | |
| 10 | |
| 11 #if defined(OS_WIN) | |
| 12 #include <windows.h> | |
| 13 #include <setupapi.h> | |
| 14 #include <winioctl.h> | |
| 15 #endif | |
| 16 | |
| 17 namespace image_writer { | |
| 18 | |
| 19 #if defined(OS_WIN) | |
| 20 const size_t kStorageQueryBufferSize = 1024; | |
| 21 #endif | |
| 22 | |
| 23 ImageWriterHandler::ImageWriterHandler() : image_writer_(this) {} | |
| 24 ImageWriterHandler::~ImageWriterHandler() {} | |
| 25 | |
| 26 void ImageWriterHandler::SendSucceeded() { | |
| 27 Send(new ChromeUtilityHostMsg_ImageWriter_Succeeded()); | |
| 28 content::UtilityThread::Get()->ReleaseProcessIfNeeded(); | |
| 29 } | |
| 30 | |
| 31 void ImageWriterHandler::SendCancelled() { | |
| 32 Send(new ChromeUtilityHostMsg_ImageWriter_Cancelled()); | |
| 33 content::UtilityThread::Get()->ReleaseProcessIfNeeded(); | |
| 34 } | |
| 35 | |
| 36 void ImageWriterHandler::SendFailed(const std::string& message) { | |
| 37 Send(new ChromeUtilityHostMsg_ImageWriter_Failed(message)); | |
| 38 content::UtilityThread::Get()->ReleaseProcessIfNeeded(); | |
| 39 } | |
| 40 | |
| 41 void ImageWriterHandler::SendProgress(int64 progress) { | |
| 42 Send(new ChromeUtilityHostMsg_ImageWriter_Progress(progress)); | |
| 43 } | |
| 44 | |
| 45 void ImageWriterHandler::Send(IPC::Message* msg) { | |
| 46 content::UtilityThread::Get()->Send(msg); | |
| 47 } | |
| 48 | |
| 49 bool ImageWriterHandler::OnMessageReceived(const IPC::Message& message) { | |
| 50 bool handled = true; | |
| 51 IPC_BEGIN_MESSAGE_MAP(ImageWriterHandler, message) | |
| 52 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ImageWriter_Write, OnWriteStart) | |
| 53 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ImageWriter_Verify, OnVerifyStart) | |
| 54 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_ImageWriter_Cancel, OnCancel) | |
| 55 IPC_MESSAGE_UNHANDLED(handled = false) | |
| 56 IPC_END_MESSAGE_MAP() | |
| 57 return handled; | |
| 58 } | |
| 59 | |
| 60 void ImageWriterHandler::OnWriteStart(const base::FilePath& image, | |
| 61 const base::FilePath& device) { | |
| 62 if (!IsValidDevice(device)) { | |
| 63 Send(new ChromeUtilityHostMsg_ImageWriter_Failed(error::kInvalidDevice)); | |
| 64 return; | |
| 65 } | |
| 66 | |
| 67 if (image_writer_.IsRunning()) { | |
| 68 Send(new ChromeUtilityHostMsg_ImageWriter_Failed( | |
| 69 error::kOperationAlreadyInProgress)); | |
| 70 return; | |
| 71 } | |
| 72 image_writer_.Write(image, device); | |
| 73 } | |
| 74 | |
| 75 void ImageWriterHandler::OnVerifyStart(const base::FilePath& image, | |
| 76 const base::FilePath& device) { | |
| 77 if (!IsValidDevice(device)) { | |
| 78 Send(new ChromeUtilityHostMsg_ImageWriter_Failed(error::kInvalidDevice)); | |
| 79 return; | |
| 80 } | |
| 81 | |
| 82 if (image_writer_.IsRunning()) { | |
| 83 Send(new ChromeUtilityHostMsg_ImageWriter_Failed( | |
| 84 error::kOperationAlreadyInProgress)); | |
| 85 return; | |
| 86 } | |
| 87 image_writer_.Verify(image, device); | |
| 88 } | |
| 89 | |
| 90 void ImageWriterHandler::OnCancel() { | |
| 91 if (image_writer_.IsRunning()) { | |
| 92 image_writer_.Cancel(); | |
| 93 } else { | |
| 94 SendCancelled(); | |
| 95 } | |
| 96 } | |
| 97 | |
| 98 bool ImageWriterHandler::IsValidDevice(const base::FilePath& device) { | |
| 99 #if defined(OS_WIN) | |
| 100 base::win::ScopedHandle device_handle( | |
| 101 CreateFile(device.value().c_str(), | |
| 102 // Desired access, which is none as we only need metadata. | |
| 103 0, | |
| 104 // Required to be read + write for devices. | |
| 105 FILE_SHARE_READ | FILE_SHARE_WRITE, | |
| 106 NULL, // Optional security attributes. | |
| 107 OPEN_EXISTING, // Devices already exist. | |
| 108 0, // No optional flags. | |
| 109 NULL)); // No template file. | |
| 110 | |
| 111 if (!device_handle) { | |
| 112 PLOG(ERROR) << "Opening device handle failed."; | |
| 113 return false; | |
| 114 } | |
| 115 | |
| 116 STORAGE_PROPERTY_QUERY query = STORAGE_PROPERTY_QUERY(); | |
| 117 query.PropertyId = StorageDeviceProperty; | |
| 118 query.QueryType = PropertyStandardQuery; | |
| 119 DWORD bytes_returned; | |
| 120 | |
| 121 scoped_ptr<char[]> output_buf(new char[kStorageQueryBufferSize]); | |
| 122 BOOL status = DeviceIoControl( | |
| 123 device_handle, // Device handle. | |
| 124 IOCTL_STORAGE_QUERY_PROPERTY, // Flag to request device properties. | |
| 125 &query, // Query parameters. | |
| 126 sizeof(STORAGE_PROPERTY_QUERY), // query parameters size. | |
| 127 output_buf.get(), // output buffer. | |
| 128 kStorageQueryBufferSize, // Size of buffer. | |
| 129 &bytes_returned, // Number of bytes returned. | |
| 130 // Must not be null. | |
| 131 NULL); // Optional unused overlapped perameter. | |
| 132 | |
| 133 if (status == FALSE) { | |
| 134 PLOG(ERROR) << "Storage property query failed."; | |
| 135 return false; | |
| 136 } | |
| 137 | |
| 138 STORAGE_DEVICE_DESCRIPTOR* device_descriptor = | |
| 139 reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(output_buf.get()); | |
| 140 | |
| 141 if (device_descriptor->RemovableMedia) | |
| 142 return true; | |
| 143 | |
| 144 #else | |
| 145 // Other platforms will have to be added as they are supported. | |
| 146 NOTIMPLEMENTED(); | |
| 147 #endif | |
| 148 return false; | |
| 149 } | |
| 150 | |
| 151 } // namespace image_writer | |
| OLD | NEW |