| Index: extensions/browser/api/usb/usb_api.cc | 
| diff --git a/extensions/browser/api/usb/usb_api.cc b/extensions/browser/api/usb/usb_api.cc | 
| index e1a4627e2e95d4fb450c0bef7b937f4d60f46d4f..4980c2d3a10468b9f0bdf6aa0f7de24d57cacac4 100644 | 
| --- a/extensions/browser/api/usb/usb_api.cc | 
| +++ b/extensions/browser/api/usb/usb_api.cc | 
| @@ -7,8 +7,8 @@ | 
| #include <string> | 
| #include <vector> | 
|  | 
| +#include "base/barrier_closure.h" | 
| #include "base/memory/scoped_ptr.h" | 
| -#include "base/message_loop/message_loop_proxy.h" | 
| #include "device/core/device_client.h" | 
| #include "device/usb/usb_device_handle.h" | 
| #include "device/usb/usb_service.h" | 
| @@ -70,9 +70,6 @@ using usb::SynchronizationType; | 
| using usb::TransferType; | 
| using usb::UsageType; | 
|  | 
| -typedef std::vector<scoped_refptr<UsbDevice> > DeviceVector; | 
| -typedef scoped_ptr<DeviceVector> ScopedDeviceVector; | 
| - | 
| namespace { | 
|  | 
| const char kDataKey[] = "data"; | 
| @@ -100,6 +97,7 @@ const char kErrorConvertDirection[] = "Invalid transfer direction."; | 
| const char kErrorConvertRecipient[] = "Invalid transfer recipient."; | 
| const char kErrorConvertRequestType[] = "Invalid request type."; | 
| const char kErrorMalformedParameters[] = "Error parsing parameters."; | 
| +const char kErrorNoConnection[] = "No such connection."; | 
| const char kErrorNoDevice[] = "No such device."; | 
| const char kErrorPermissionDenied[] = "Permission to access device was denied"; | 
| const char kErrorInvalidTransferLength[] = | 
| @@ -242,58 +240,6 @@ const char* ConvertTransferStatusToApi(const UsbTransferStatus status) { | 
| } | 
| } | 
|  | 
| -#if defined(OS_CHROMEOS) | 
| -void RequestUsbDevicesAccessHelper( | 
| -    ScopedDeviceVector devices, | 
| -    std::vector<scoped_refptr<UsbDevice> >::iterator i, | 
| -    int interface_id, | 
| -    const base::Callback<void(ScopedDeviceVector result)>& callback, | 
| -    bool success) { | 
| -  if (success) { | 
| -    ++i; | 
| -  } else { | 
| -    i = devices->erase(i); | 
| -  } | 
| -  if (i == devices->end()) { | 
| -    callback.Run(devices.Pass()); | 
| -    return; | 
| -  } | 
| -  (*i)->RequestUsbAccess(interface_id, | 
| -                         base::Bind(RequestUsbDevicesAccessHelper, | 
| -                                    base::Passed(devices.Pass()), | 
| -                                    i, | 
| -                                    interface_id, | 
| -                                    callback)); | 
| -} | 
| - | 
| -void RequestUsbDevicesAccess( | 
| -    ScopedDeviceVector devices, | 
| -    int interface_id, | 
| -    const base::Callback<void(ScopedDeviceVector result)>& callback) { | 
| -  if (devices->empty()) { | 
| -    callback.Run(devices.Pass()); | 
| -    return; | 
| -  } | 
| -  std::vector<scoped_refptr<UsbDevice> >::iterator i = devices->begin(); | 
| -  (*i)->RequestUsbAccess(interface_id, | 
| -                         base::Bind(RequestUsbDevicesAccessHelper, | 
| -                                    base::Passed(devices.Pass()), | 
| -                                    i, | 
| -                                    interface_id, | 
| -                                    callback)); | 
| -} | 
| -#endif  // OS_CHROMEOS | 
| - | 
| -base::DictionaryValue* CreateTransferInfo(UsbTransferStatus status, | 
| -                                          scoped_refptr<net::IOBuffer> data, | 
| -                                          size_t length) { | 
| -  base::DictionaryValue* result = new base::DictionaryValue(); | 
| -  result->SetInteger(kResultCodeKey, status); | 
| -  result->Set(kDataKey, | 
| -              base::BinaryValue::CreateWithCopiedBuffer(data->data(), length)); | 
| -  return result; | 
| -} | 
| - | 
| base::Value* PopulateConnectionHandle(int handle, | 
| int vendor_id, | 
| int product_id) { | 
| @@ -436,31 +382,25 @@ void ConvertDeviceFilter(const usb::DeviceFilter& input, | 
|  | 
| namespace extensions { | 
|  | 
| -UsbAsyncApiFunction::UsbAsyncApiFunction() : manager_(NULL) { | 
| -} | 
| - | 
| -UsbAsyncApiFunction::~UsbAsyncApiFunction() { | 
| +UsbPermissionCheckingFunction::UsbPermissionCheckingFunction() | 
| +    : device_permissions_manager_(nullptr) { | 
| } | 
|  | 
| -bool UsbAsyncApiFunction::PrePrepare() { | 
| -  manager_ = ApiResourceManager<UsbDeviceResource>::Get(browser_context()); | 
| -  set_work_thread_id(BrowserThread::FILE); | 
| -  return manager_ != NULL; | 
| +UsbPermissionCheckingFunction::~UsbPermissionCheckingFunction() { | 
| } | 
|  | 
| -bool UsbAsyncApiFunction::Respond() { | 
| -  return error_.empty(); | 
| -} | 
| - | 
| -bool UsbAsyncApiFunction::HasDevicePermission(scoped_refptr<UsbDevice> device) { | 
| -  DCHECK(device_permissions_); | 
| +bool UsbPermissionCheckingFunction::HasDevicePermission( | 
| +    scoped_refptr<UsbDevice> device) { | 
| +  if (!device_permissions_manager_) { | 
| +    device_permissions_manager_ = | 
| +        DevicePermissionsManager::Get(browser_context()); | 
| +  } | 
|  | 
| -  // Check the DevicePermissionsManager first so that if an entry is found | 
| -  // it can be stored for later. This requires the serial number. | 
| -  base::string16 serial_number; | 
| -  device->GetSerialNumber(&serial_number); | 
| +  DevicePermissions* device_permissions = | 
| +      device_permissions_manager_->GetForExtension(extension_id()); | 
| +  DCHECK(device_permissions); | 
|  | 
| -  permission_entry_ = device_permissions_->FindEntry(device, serial_number); | 
| +  permission_entry_ = device_permissions->FindEntry(device); | 
| if (permission_entry_.get()) { | 
| return true; | 
| } | 
| @@ -477,83 +417,65 @@ bool UsbAsyncApiFunction::HasDevicePermission(scoped_refptr<UsbDevice> device) { | 
| return false; | 
| } | 
|  | 
| -scoped_refptr<UsbDeviceHandle> | 
| -UsbAsyncApiFunction::GetDeviceHandleOrCompleteWithError( | 
| -    const ConnectionHandle& input_device_handle) { | 
| -  UsbDeviceResource* resource = | 
| -      manager_->Get(extension_->id(), input_device_handle.handle); | 
| -  if (!resource) { | 
| -    CompleteWithError(kErrorNoDevice); | 
| -    return NULL; | 
| -  } | 
| - | 
| -  if (!resource->device().get() || !resource->device()->GetDevice().get()) { | 
| -    CompleteWithError(kErrorDisconnect); | 
| -    manager_->Remove(extension_->id(), input_device_handle.handle); | 
| -    return NULL; | 
| -  } | 
| - | 
| -  if (resource->device()->GetDevice()->vendor_id() != | 
| -          input_device_handle.vendor_id || | 
| -      resource->device()->GetDevice()->product_id() != | 
| -          input_device_handle.product_id) { | 
| -    CompleteWithError(kErrorNoDevice); | 
| -    return NULL; | 
| +void UsbPermissionCheckingFunction::RecordDeviceLastUsed() { | 
| +  if (permission_entry_.get()) { | 
| +    device_permissions_manager_->UpdateLastUsed(extension_id(), | 
| +                                                permission_entry_); | 
| } | 
| - | 
| -  return resource->device(); | 
| } | 
|  | 
| -void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id) { | 
| -  manager_->Remove(extension_->id(), api_resource_id); | 
| +UsbConnectionFunction::UsbConnectionFunction() { | 
| } | 
|  | 
| -void UsbAsyncApiFunction::CompleteWithError(const std::string& error) { | 
| -  SetError(error); | 
| -  AsyncWorkCompleted(); | 
| +UsbConnectionFunction::~UsbConnectionFunction() { | 
| } | 
|  | 
| -UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() { | 
| -} | 
| +scoped_refptr<device::UsbDeviceHandle> UsbConnectionFunction::GetDeviceHandle( | 
| +    const extensions::core_api::usb::ConnectionHandle& handle) { | 
| +  ApiResourceManager<UsbDeviceResource>* manager = | 
| +      ApiResourceManager<UsbDeviceResource>::Get(browser_context()); | 
| +  if (!manager) { | 
| +    return nullptr; | 
| +  } | 
|  | 
| -UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() { | 
| -} | 
| +  UsbDeviceResource* resource = manager->Get(extension_id(), handle.handle); | 
| +  if (!resource) { | 
| +    return nullptr; | 
| +  } | 
|  | 
| -void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status, | 
| -                                              scoped_refptr<net::IOBuffer> data, | 
| -                                              size_t length) { | 
| -  if (status != device::USB_TRANSFER_COMPLETED) | 
| -    SetError(ConvertTransferStatusToApi(status)); | 
| +  return resource->device(); | 
| +} | 
|  | 
| -  SetResult(CreateTransferInfo(status, data, length)); | 
| -  AsyncWorkCompleted(); | 
| +void UsbConnectionFunction::ReleaseDeviceHandle( | 
| +    const extensions::core_api::usb::ConnectionHandle& handle) { | 
| +  ApiResourceManager<UsbDeviceResource>* manager = | 
| +      ApiResourceManager<UsbDeviceResource>::Get(browser_context()); | 
| +  manager->Remove(extension_id(), handle.handle); | 
| } | 
|  | 
| -bool UsbAsyncApiTransferFunction::ConvertDirectionSafely( | 
| -    const Direction& input, | 
| -    UsbEndpointDirection* output) { | 
| -  const bool converted = ConvertDirectionFromApi(input, output); | 
| -  if (!converted) | 
| -    SetError(kErrorConvertDirection); | 
| -  return converted; | 
| +UsbTransferFunction::UsbTransferFunction() { | 
| } | 
|  | 
| -bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely( | 
| -    const RequestType& input, | 
| -    UsbDeviceHandle::TransferRequestType* output) { | 
| -  const bool converted = ConvertRequestTypeFromApi(input, output); | 
| -  if (!converted) | 
| -    SetError(kErrorConvertRequestType); | 
| -  return converted; | 
| +UsbTransferFunction::~UsbTransferFunction() { | 
| } | 
|  | 
| -bool UsbAsyncApiTransferFunction::ConvertRecipientSafely( | 
| -    const Recipient& input, | 
| -    UsbDeviceHandle::TransferRecipient* output) { | 
| -  const bool converted = ConvertRecipientFromApi(input, output); | 
| -  if (!converted) | 
| -    SetError(kErrorConvertRecipient); | 
| -  return converted; | 
| +void UsbTransferFunction::OnCompleted(UsbTransferStatus status, | 
| +                                      scoped_refptr<net::IOBuffer> data, | 
| +                                      size_t length) { | 
| +  scoped_ptr<base::DictionaryValue> transfer_info(new base::DictionaryValue()); | 
| +  transfer_info->SetInteger(kResultCodeKey, status); | 
| +  transfer_info->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer( | 
| +                                   data->data(), length)); | 
| + | 
| +  if (status == device::USB_TRANSFER_COMPLETED) { | 
| +    Respond(OneArgument(transfer_info.release())); | 
| +  } else { | 
| +    scoped_ptr<base::ListValue> error_args(new base::ListValue()); | 
| +    error_args->Append(transfer_info.release()); | 
| +    // Returning arguments with an error is wrong but we're stuck with it. | 
| +    Respond(ErrorWithArguments(error_args.Pass(), | 
| +                               ConvertTransferStatusToApi(status))); | 
| +  } | 
| } | 
|  | 
| UsbFindDevicesFunction::UsbFindDevicesFunction() { | 
| @@ -562,75 +484,85 @@ UsbFindDevicesFunction::UsbFindDevicesFunction() { | 
| UsbFindDevicesFunction::~UsbFindDevicesFunction() { | 
| } | 
|  | 
| -bool UsbFindDevicesFunction::Prepare() { | 
| -  parameters_ = FindDevices::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbFindDevicesFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::FindDevices::Params> parameters = | 
| +      FindDevices::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbFindDevicesFunction::AsyncWorkStart() { | 
| -  scoped_ptr<base::ListValue> result(new base::ListValue()); | 
| -  const uint16_t vendor_id = parameters_->options.vendor_id; | 
| -  const uint16_t product_id = parameters_->options.product_id; | 
| -  int interface_id = parameters_->options.interface_id.get() | 
| -                         ? *parameters_->options.interface_id.get() | 
| -                         : UsbDevicePermissionData::ANY_INTERFACE; | 
| -  UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id); | 
| +  vendor_id_ = parameters->options.vendor_id; | 
| +  product_id_ = parameters->options.product_id; | 
| +  interface_id_ = parameters->options.interface_id.get() | 
| +                      ? *parameters->options.interface_id.get() | 
| +                      : UsbDevicePermissionData::ANY_INTERFACE; | 
| +  UsbDevicePermission::CheckParam param(vendor_id_, product_id_, interface_id_); | 
| if (!extension()->permissions_data()->CheckAPIPermissionWithParam( | 
| APIPermission::kUsbDevice, ¶m)) { | 
| -    LOG(WARNING) << "Insufficient permissions to access device."; | 
| -    CompleteWithError(kErrorPermissionDenied); | 
| -    return; | 
| +    return RespondNow(Error(kErrorPermissionDenied)); | 
| } | 
|  | 
| UsbService* service = device::DeviceClient::Get()->GetUsbService(); | 
| if (!service) { | 
| -    CompleteWithError(kErrorInitService); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInitService)); | 
| } | 
|  | 
| -  ScopedDeviceVector devices(new DeviceVector()); | 
| -  service->GetDevices(devices.get()); | 
| +  service->GetDevices( | 
| +      base::Bind(&UsbFindDevicesFunction::OnGetDevicesComplete, this)); | 
| +  return RespondLater(); | 
| +} | 
|  | 
| -  for (DeviceVector::iterator it = devices->begin(); it != devices->end();) { | 
| -    if ((*it)->vendor_id() != vendor_id || (*it)->product_id() != product_id) { | 
| -      it = devices->erase(it); | 
| +void UsbFindDevicesFunction::OnGetDevicesComplete( | 
| +    const std::vector<scoped_refptr<UsbDevice>>& devices) { | 
| +  result_.reset(new base::ListValue()); | 
| +  barrier_ = base::BarrierClosure( | 
| +      devices.size(), base::Bind(&UsbFindDevicesFunction::OpenComplete, this)); | 
| + | 
| +  for (const scoped_refptr<UsbDevice>& device : devices) { | 
| +    if (device->vendor_id() != vendor_id_ || | 
| +        device->product_id() != product_id_) { | 
| +      barrier_.Run(); | 
| } else { | 
| -      ++it; | 
| -    } | 
| -  } | 
| - | 
| #if defined(OS_CHROMEOS) | 
| -  RequestUsbDevicesAccess( | 
| -      devices.Pass(), | 
| -      interface_id, | 
| -      base::Bind(&UsbFindDevicesFunction::OpenDevices, this)); | 
| +      device->RequestUsbAccess( | 
| +          interface_id_, | 
| +          base::Bind(&UsbFindDevicesFunction::OnRequestAccessComplete, this, | 
| +                     device)); | 
| #else | 
| -  OpenDevices(devices.Pass()); | 
| -#endif  // OS_CHROMEOS | 
| +      device->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened, this)); | 
| +#endif | 
| +    } | 
| +  } | 
| } | 
|  | 
| -void UsbFindDevicesFunction::OpenDevices(ScopedDeviceVector devices) { | 
| -  base::ListValue* result = new base::ListValue(); | 
| +#if defined(OS_CHROMEOS) | 
|  | 
| -  for (size_t i = 0; i < devices->size(); ++i) { | 
| -    scoped_refptr<UsbDeviceHandle> device_handle = devices->at(i)->Open(); | 
| -    if (device_handle.get()) | 
| -      device_handles_.push_back(device_handle); | 
| +void UsbFindDevicesFunction::OnRequestAccessComplete( | 
| +    scoped_refptr<UsbDevice> device, | 
| +    bool success) { | 
| +  if (success) { | 
| +    device->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened, this)); | 
| +  } else { | 
| +    barrier_.Run(); | 
| } | 
| +} | 
|  | 
| -  for (size_t i = 0; i < device_handles_.size(); ++i) { | 
| -    UsbDeviceHandle* const device_handle = device_handles_[i].get(); | 
| -    UsbDeviceResource* const resource = | 
| -        new UsbDeviceResource(extension_->id(), device_handle); | 
| +#endif  // OS_CHROMEOS | 
|  | 
| -    result->Append(PopulateConnectionHandle(manager_->Add(resource), | 
| -                                            parameters_->options.vendor_id, | 
| -                                            parameters_->options.product_id)); | 
| +void UsbFindDevicesFunction::OnDeviceOpened( | 
| +    scoped_refptr<UsbDeviceHandle> device_handle) { | 
| +  if (device_handle.get()) { | 
| +    ApiResourceManager<UsbDeviceResource>* manager = | 
| +        ApiResourceManager<UsbDeviceResource>::Get(browser_context()); | 
| +    UsbDeviceResource* resource = | 
| +        new UsbDeviceResource(extension_id(), device_handle); | 
| +    scoped_refptr<UsbDevice> device = device_handle->GetDevice(); | 
| +    result_->Append(PopulateConnectionHandle( | 
| +        manager->Add(resource), device->vendor_id(), device->product_id())); | 
| } | 
| +  barrier_.Run(); | 
| +} | 
|  | 
| -  SetResult(result); | 
| -  AsyncWorkCompleted(); | 
| +void UsbFindDevicesFunction::OpenComplete() { | 
| +  Respond(OneArgument(result_.release())); | 
| } | 
|  | 
| UsbGetDevicesFunction::UsbGetDevicesFunction() { | 
| @@ -639,51 +571,47 @@ UsbGetDevicesFunction::UsbGetDevicesFunction() { | 
| UsbGetDevicesFunction::~UsbGetDevicesFunction() { | 
| } | 
|  | 
| -bool UsbGetDevicesFunction::Prepare() { | 
| -  parameters_ = GetDevices::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  device_permissions_ = DevicePermissionsManager::Get(browser_context()) | 
| -                            ->GetForExtension(extension()->id()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbGetDevicesFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::GetDevices::Params> parameters = | 
| +      GetDevices::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbGetDevicesFunction::AsyncWorkStart() { | 
| -  std::vector<UsbDeviceFilter> filters; | 
| -  if (parameters_->options.filters) { | 
| -    filters.resize(parameters_->options.filters->size()); | 
| -    for (size_t i = 0; i < parameters_->options.filters->size(); ++i) { | 
| -      ConvertDeviceFilter(*parameters_->options.filters->at(i).get(), | 
| -                          &filters[i]); | 
| +  if (parameters->options.filters) { | 
| +    filters_.resize(parameters->options.filters->size()); | 
| +    for (size_t i = 0; i < parameters->options.filters->size(); ++i) { | 
| +      ConvertDeviceFilter(*parameters->options.filters->at(i).get(), | 
| +                          &filters_[i]); | 
| } | 
| } | 
| -  if (parameters_->options.vendor_id) { | 
| -    filters.resize(filters.size() + 1); | 
| -    filters.back().SetVendorId(*parameters_->options.vendor_id); | 
| -    if (parameters_->options.product_id) { | 
| -      filters.back().SetProductId(*parameters_->options.product_id); | 
| +  if (parameters->options.vendor_id) { | 
| +    filters_.resize(filters_.size() + 1); | 
| +    filters_.back().SetVendorId(*parameters->options.vendor_id); | 
| +    if (parameters->options.product_id) { | 
| +      filters_.back().SetProductId(*parameters->options.product_id); | 
| } | 
| } | 
|  | 
| UsbService* service = device::DeviceClient::Get()->GetUsbService(); | 
| if (!service) { | 
| -    CompleteWithError(kErrorInitService); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInitService)); | 
| } | 
|  | 
| -  DeviceVector devices; | 
| -  service->GetDevices(&devices); | 
| +  service->GetDevices( | 
| +      base::Bind(&UsbGetDevicesFunction::OnGetDevicesComplete, this)); | 
| +  return RespondLater(); | 
| +} | 
|  | 
| +void UsbGetDevicesFunction::OnGetDevicesComplete( | 
| +    const std::vector<scoped_refptr<UsbDevice>>& devices) { | 
| scoped_ptr<base::ListValue> result(new base::ListValue()); | 
| -  for (DeviceVector::iterator it = devices.begin(); it != devices.end(); ++it) { | 
| -    scoped_refptr<UsbDevice> device = *it; | 
| -    if ((filters.empty() || UsbDeviceFilter::MatchesAny(device, filters)) && | 
| +  for (const scoped_refptr<UsbDevice>& device : devices) { | 
| +    if ((filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_)) && | 
| HasDevicePermission(device)) { | 
| -      result->Append(PopulateDevice(it->get())); | 
| +      result->Append(PopulateDevice(device.get())); | 
| } | 
| } | 
|  | 
| -  SetResult(result.release()); | 
| -  AsyncWorkCompleted(); | 
| +  Respond(OneArgument(result.release())); | 
| } | 
|  | 
| UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() { | 
| @@ -692,7 +620,7 @@ UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() { | 
| UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() { | 
| } | 
|  | 
| -AsyncApiFunction::ResponseAction UsbGetUserSelectedDevicesFunction::Run() { | 
| +ExtensionFunction::ResponseAction UsbGetUserSelectedDevicesFunction::Run() { | 
| scoped_ptr<extensions::core_api::usb::GetUserSelectedDevices::Params> | 
| parameters = GetUserSelectedDevices::Params::Create(*args_); | 
| EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
| @@ -734,8 +662,7 @@ void UsbGetUserSelectedDevicesFunction::OnUsbDevicesChosen( | 
| result->Append(PopulateDevice(device.get())); | 
| } | 
|  | 
| -  SetResult(result.release()); | 
| -  SendResponse(true); | 
| +  Respond(OneArgument(result.release())); | 
| Release(); | 
| } | 
|  | 
| @@ -745,15 +672,11 @@ UsbRequestAccessFunction::UsbRequestAccessFunction() { | 
| UsbRequestAccessFunction::~UsbRequestAccessFunction() { | 
| } | 
|  | 
| -bool UsbRequestAccessFunction::Prepare() { | 
| -  parameters_ = RequestAccess::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| - | 
| -void UsbRequestAccessFunction::AsyncWorkStart() { | 
| -  SetResult(new base::FundamentalValue(true)); | 
| -  AsyncWorkCompleted(); | 
| +ExtensionFunction::ResponseAction UsbRequestAccessFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::RequestAccess::Params> parameters = | 
| +      RequestAccess::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
| +  return RespondNow(OneArgument(new base::FundamentalValue(true))); | 
| } | 
|  | 
| UsbOpenDeviceFunction::UsbOpenDeviceFunction() { | 
| @@ -762,71 +685,65 @@ UsbOpenDeviceFunction::UsbOpenDeviceFunction() { | 
| UsbOpenDeviceFunction::~UsbOpenDeviceFunction() { | 
| } | 
|  | 
| -bool UsbOpenDeviceFunction::Prepare() { | 
| -  parameters_ = OpenDevice::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  device_permissions_manager_ = | 
| -      DevicePermissionsManager::Get(browser_context()); | 
| -  device_permissions_ = | 
| -      device_permissions_manager_->GetForExtension(extension()->id()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbOpenDeviceFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::OpenDevice::Params> parameters = | 
| +      OpenDevice::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbOpenDeviceFunction::AsyncWorkStart() { | 
| UsbService* service = device::DeviceClient::Get()->GetUsbService(); | 
| if (!service) { | 
| -    CompleteWithError(kErrorInitService); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInitService)); | 
| } | 
|  | 
| -  device_ = service->GetDeviceById(parameters_->device.device); | 
| -  if (!device_.get()) { | 
| -    CompleteWithError(kErrorNoDevice); | 
| -    return; | 
| +  scoped_refptr<UsbDevice> device = | 
| +      service->GetDeviceById(parameters->device.device); | 
| +  if (!device.get()) { | 
| +    return RespondNow(Error(kErrorNoDevice)); | 
| } | 
|  | 
| -  if (!HasDevicePermission(device_)) { | 
| +  if (!HasDevicePermission(device)) { | 
| // This function must act as if there is no such device. Otherwise it can be | 
| // used to fingerprint unauthorized devices. | 
| -    CompleteWithError(kErrorNoDevice); | 
| -    return; | 
| +    return RespondNow(Error(kErrorNoDevice)); | 
| } | 
|  | 
| #if defined(OS_CHROMEOS) | 
| -  device_->RequestUsbAccess( | 
| +  device->RequestUsbAccess( | 
| -1, /* any interface, unused by the permission broker */ | 
| -      base::Bind(&UsbOpenDeviceFunction::OnRequestAccessComplete, this)); | 
| +      base::Bind(&UsbOpenDeviceFunction::OnRequestAccessComplete, this, | 
| +                 device)); | 
| #else | 
| -  OnRequestAccessComplete(true); | 
| +  device->Open(base::Bind(&UsbOpenDeviceFunction::OnDeviceOpened, this)); | 
| #endif  // OS_CHROMEOS | 
| + | 
| +  return RespondLater(); | 
| } | 
|  | 
| -void UsbOpenDeviceFunction::OnRequestAccessComplete(bool success) { | 
| -  if (!success) { | 
| -    SetError(kErrorPermissionDenied); | 
| -    AsyncWorkCompleted(); | 
| -    return; | 
| +void UsbOpenDeviceFunction::OnRequestAccessComplete( | 
| +    scoped_refptr<UsbDevice> device, | 
| +    bool success) { | 
| +  if (success) { | 
| +    device->Open(base::Bind(&UsbOpenDeviceFunction::OnDeviceOpened, this)); | 
| +  } else { | 
| +    Respond(Error(kErrorPermissionDenied)); | 
| } | 
| +} | 
|  | 
| -  scoped_refptr<UsbDeviceHandle> handle = device_->Open(); | 
| -  if (!handle.get()) { | 
| -    SetError(kErrorOpen); | 
| -    AsyncWorkCompleted(); | 
| +void UsbOpenDeviceFunction::OnDeviceOpened( | 
| +    scoped_refptr<UsbDeviceHandle> device_handle) { | 
| +  if (!device_handle.get()) { | 
| +    Respond(Error(kErrorOpen)); | 
| return; | 
| } | 
|  | 
| -  SetResult(PopulateConnectionHandle( | 
| -      manager_->Add(new UsbDeviceResource(extension_->id(), handle)), | 
| -      device_->vendor_id(), device_->product_id())); | 
| -  AsyncWorkCompleted(); | 
| -} | 
| +  RecordDeviceLastUsed(); | 
|  | 
| -bool UsbOpenDeviceFunction::Respond() { | 
| -  if (permission_entry_.get()) { | 
| -    device_permissions_manager_->UpdateLastUsed(extension_->id(), | 
| -                                                permission_entry_); | 
| -  } | 
| -  return UsbAsyncApiFunction::Respond(); | 
| +  ApiResourceManager<UsbDeviceResource>* manager = | 
| +      ApiResourceManager<UsbDeviceResource>::Get(browser_context()); | 
| +  scoped_refptr<UsbDevice> device = device_handle->GetDevice(); | 
| +  Respond(OneArgument(PopulateConnectionHandle( | 
| +      manager->Add(new UsbDeviceResource(extension_id(), device_handle)), | 
| +      device->vendor_id(), device->product_id()))); | 
| } | 
|  | 
| UsbSetConfigurationFunction::UsbSetConfigurationFunction() { | 
| @@ -835,23 +752,29 @@ UsbSetConfigurationFunction::UsbSetConfigurationFunction() { | 
| UsbSetConfigurationFunction::~UsbSetConfigurationFunction() { | 
| } | 
|  | 
| -bool UsbSetConfigurationFunction::Prepare() { | 
| -  parameters_ = SetConfiguration::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbSetConfigurationFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::SetConfiguration::Params> parameters = | 
| +      SetConfiguration::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbSetConfigurationFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| +      GetDeviceHandle(parameters->handle); | 
| if (!device_handle.get()) { | 
| -    return; | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| } | 
|  | 
| -  if (!device_handle->SetConfiguration(parameters_->configuration_value)) { | 
| -    SetError(kErrorCannotSetConfiguration); | 
| +  device_handle->SetConfiguration( | 
| +      parameters->configuration_value, | 
| +      base::Bind(&UsbSetConfigurationFunction::OnComplete, this)); | 
| +  return RespondLater(); | 
| +} | 
| + | 
| +void UsbSetConfigurationFunction::OnComplete(bool success) { | 
| +  if (success) { | 
| +    Respond(NoArguments()); | 
| +  } else { | 
| +    Respond(Error(kErrorCannotSetConfiguration)); | 
| } | 
| -  AsyncWorkCompleted(); | 
| } | 
|  | 
| UsbGetConfigurationFunction::UsbGetConfigurationFunction() { | 
| @@ -860,17 +783,15 @@ UsbGetConfigurationFunction::UsbGetConfigurationFunction() { | 
| UsbGetConfigurationFunction::~UsbGetConfigurationFunction() { | 
| } | 
|  | 
| -bool UsbGetConfigurationFunction::Prepare() { | 
| -  parameters_ = GetConfiguration::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbGetConfigurationFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::GetConfiguration::Params> parameters = | 
| +      GetConfiguration::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbGetConfigurationFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| +      GetDeviceHandle(parameters->handle); | 
| if (!device_handle.get()) { | 
| -    return; | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| } | 
|  | 
| const UsbConfigDescriptor* config_descriptor = | 
| @@ -878,12 +799,10 @@ void UsbGetConfigurationFunction::AsyncWorkStart() { | 
| if (config_descriptor) { | 
| ConfigDescriptor config; | 
| ConvertConfigDescriptor(*config_descriptor, &config); | 
| -    SetResult(config.ToValue().release()); | 
| +    return RespondNow(OneArgument(config.ToValue().release())); | 
| } else { | 
| -    SetError(kErrorNotConfigured); | 
| +    return RespondNow(Error(kErrorNotConfigured)); | 
| } | 
| - | 
| -  AsyncWorkCompleted(); | 
| } | 
|  | 
| UsbListInterfacesFunction::UsbListInterfacesFunction() { | 
| @@ -892,17 +811,15 @@ UsbListInterfacesFunction::UsbListInterfacesFunction() { | 
| UsbListInterfacesFunction::~UsbListInterfacesFunction() { | 
| } | 
|  | 
| -bool UsbListInterfacesFunction::Prepare() { | 
| -  parameters_ = ListInterfaces::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbListInterfacesFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::ListInterfaces::Params> parameters = | 
| +      ListInterfaces::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbListInterfacesFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| +      GetDeviceHandle(parameters->handle); | 
| if (!device_handle.get()) { | 
| -    return; | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| } | 
|  | 
| const UsbConfigDescriptor* config_descriptor = | 
| @@ -916,12 +833,10 @@ void UsbListInterfacesFunction::AsyncWorkStart() { | 
| result->Append(config.interfaces[i]->ToValue().release()); | 
| } | 
|  | 
| -    SetResult(result.release()); | 
| +    return RespondNow(OneArgument(result.release())); | 
| } else { | 
| -    SetError(kErrorNotConfigured); | 
| +    return RespondNow(Error(kErrorNotConfigured)); | 
| } | 
| - | 
| -  AsyncWorkCompleted(); | 
| } | 
|  | 
| UsbCloseDeviceFunction::UsbCloseDeviceFunction() { | 
| @@ -930,21 +845,20 @@ UsbCloseDeviceFunction::UsbCloseDeviceFunction() { | 
| UsbCloseDeviceFunction::~UsbCloseDeviceFunction() { | 
| } | 
|  | 
| -bool UsbCloseDeviceFunction::Prepare() { | 
| -  parameters_ = CloseDevice::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbCloseDeviceFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::CloseDevice::Params> parameters = | 
| +      CloseDevice::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbCloseDeviceFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| -  if (!device_handle.get()) | 
| -    return; | 
| +      GetDeviceHandle(parameters->handle); | 
| +  if (!device_handle.get()) { | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| +  } | 
|  | 
| // The device handle is closed when the resource is destroyed. | 
| -  RemoveUsbDeviceResource(parameters_->handle.handle); | 
| -  AsyncWorkCompleted(); | 
| +  ReleaseDeviceHandle(parameters->handle); | 
| +  return RespondNow(NoArguments()); | 
| } | 
|  | 
| UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() { | 
| @@ -953,23 +867,29 @@ UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() { | 
| UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() { | 
| } | 
|  | 
| -bool UsbClaimInterfaceFunction::Prepare() { | 
| -  parameters_ = ClaimInterface::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbClaimInterfaceFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::ClaimInterface::Params> parameters = | 
| +      ClaimInterface::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbClaimInterfaceFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| -  if (!device_handle.get()) | 
| -    return; | 
| +      GetDeviceHandle(parameters->handle); | 
| +  if (!device_handle.get()) { | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| +  } | 
|  | 
| -  bool success = device_handle->ClaimInterface(parameters_->interface_number); | 
| +  device_handle->ClaimInterface( | 
| +      parameters->interface_number, | 
| +      base::Bind(&UsbClaimInterfaceFunction::OnComplete, this)); | 
| +  return RespondLater(); | 
| +} | 
|  | 
| -  if (!success) | 
| -    SetError(kErrorCannotClaimInterface); | 
| -  AsyncWorkCompleted(); | 
| +void UsbClaimInterfaceFunction::OnComplete(bool success) { | 
| +  if (success) { | 
| +    Respond(NoArguments()); | 
| +  } else { | 
| +    Respond(Error(kErrorCannotClaimInterface)); | 
| +  } | 
| } | 
|  | 
| UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() { | 
| @@ -978,22 +898,22 @@ UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() { | 
| UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() { | 
| } | 
|  | 
| -bool UsbReleaseInterfaceFunction::Prepare() { | 
| -  parameters_ = ReleaseInterface::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbReleaseInterfaceFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::ReleaseInterface::Params> parameters = | 
| +      ReleaseInterface::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbReleaseInterfaceFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| -  if (!device_handle.get()) | 
| -    return; | 
| +      GetDeviceHandle(parameters->handle); | 
| +  if (!device_handle.get()) { | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| +  } | 
|  | 
| -  bool success = device_handle->ReleaseInterface(parameters_->interface_number); | 
| -  if (!success) | 
| -    SetError(kErrorCannotReleaseInterface); | 
| -  AsyncWorkCompleted(); | 
| +  if (device_handle->ReleaseInterface(parameters->interface_number)) { | 
| +    return RespondNow(NoArguments()); | 
| +  } else { | 
| +    return RespondNow(Error(kErrorCannotReleaseInterface)); | 
| +  } | 
| } | 
|  | 
| UsbSetInterfaceAlternateSettingFunction:: | 
| @@ -1004,24 +924,30 @@ UsbSetInterfaceAlternateSettingFunction:: | 
| ~UsbSetInterfaceAlternateSettingFunction() { | 
| } | 
|  | 
| -bool UsbSetInterfaceAlternateSettingFunction::Prepare() { | 
| -  parameters_ = SetInterfaceAlternateSetting::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction | 
| +UsbSetInterfaceAlternateSettingFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::SetInterfaceAlternateSetting::Params> | 
| +      parameters = SetInterfaceAlternateSetting::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| -  if (!device_handle.get()) | 
| -    return; | 
| +      GetDeviceHandle(parameters->handle); | 
| +  if (!device_handle.get()) { | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| +  } | 
|  | 
| -  bool success = device_handle->SetInterfaceAlternateSetting( | 
| -      parameters_->interface_number, parameters_->alternate_setting); | 
| -  if (!success) | 
| -    SetError(kErrorCannotSetInterfaceAlternateSetting); | 
| +  device_handle->SetInterfaceAlternateSetting( | 
| +      parameters->interface_number, parameters->alternate_setting, | 
| +      base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnComplete, this)); | 
| +  return RespondLater(); | 
| +} | 
|  | 
| -  AsyncWorkCompleted(); | 
| +void UsbSetInterfaceAlternateSettingFunction::OnComplete(bool success) { | 
| +  if (success) { | 
| +    Respond(NoArguments()); | 
| +  } else { | 
| +    Respond(Error(kErrorCannotSetInterfaceAlternateSetting)); | 
| +  } | 
| } | 
|  | 
| UsbControlTransferFunction::UsbControlTransferFunction() { | 
| @@ -1030,54 +956,55 @@ UsbControlTransferFunction::UsbControlTransferFunction() { | 
| UsbControlTransferFunction::~UsbControlTransferFunction() { | 
| } | 
|  | 
| -bool UsbControlTransferFunction::Prepare() { | 
| -  parameters_ = ControlTransfer::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbControlTransferFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::ControlTransfer::Params> parameters = | 
| +      ControlTransfer::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbControlTransferFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| -  if (!device_handle.get()) | 
| -    return; | 
| - | 
| -  const ControlTransferInfo& transfer = parameters_->transfer_info; | 
| +      GetDeviceHandle(parameters->handle); | 
| +  if (!device_handle.get()) { | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| +  } | 
|  | 
| +  const ControlTransferInfo& transfer = parameters->transfer_info; | 
| UsbEndpointDirection direction; | 
| UsbDeviceHandle::TransferRequestType request_type; | 
| UsbDeviceHandle::TransferRecipient recipient; | 
| size_t size = 0; | 
|  | 
| -  if (!ConvertDirectionSafely(transfer.direction, &direction) || | 
| -      !ConvertRequestTypeSafely(transfer.request_type, &request_type) || | 
| -      !ConvertRecipientSafely(transfer.recipient, &recipient)) { | 
| -    AsyncWorkCompleted(); | 
| -    return; | 
| +  if (!ConvertDirectionFromApi(transfer.direction, &direction)) { | 
| +    return RespondNow(Error(kErrorConvertDirection)); | 
| +  } | 
| + | 
| +  if (!ConvertRequestTypeFromApi(transfer.request_type, &request_type)) { | 
| +    return RespondNow(Error(kErrorConvertRequestType)); | 
| +  } | 
| + | 
| +  if (!ConvertRecipientFromApi(transfer.recipient, &recipient)) { | 
| +    return RespondNow(Error(kErrorConvertRecipient)); | 
| } | 
|  | 
| if (!GetTransferSize(transfer, &size)) { | 
| -    CompleteWithError(kErrorInvalidTransferLength); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidTransferLength)); | 
| } | 
|  | 
| scoped_refptr<net::IOBuffer> buffer = | 
| CreateBufferForTransfer(transfer, direction, size); | 
| if (!buffer.get()) { | 
| -    CompleteWithError(kErrorMalformedParameters); | 
| -    return; | 
| +    return RespondNow(Error(kErrorMalformedParameters)); | 
| } | 
|  | 
| int timeout = transfer.timeout ? *transfer.timeout : 0; | 
| if (timeout < 0) { | 
| -    CompleteWithError(kErrorInvalidTimeout); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidTimeout)); | 
| } | 
|  | 
| device_handle->ControlTransfer( | 
| direction, request_type, recipient, transfer.request, transfer.value, | 
| transfer.index, buffer.get(), size, timeout, | 
| base::Bind(&UsbControlTransferFunction::OnCompleted, this)); | 
| +  return RespondLater(); | 
| } | 
|  | 
| UsbBulkTransferFunction::UsbBulkTransferFunction() { | 
| @@ -1086,49 +1013,44 @@ UsbBulkTransferFunction::UsbBulkTransferFunction() { | 
| UsbBulkTransferFunction::~UsbBulkTransferFunction() { | 
| } | 
|  | 
| -bool UsbBulkTransferFunction::Prepare() { | 
| -  parameters_ = BulkTransfer::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbBulkTransferFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::BulkTransfer::Params> parameters = | 
| +      BulkTransfer::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbBulkTransferFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| -  if (!device_handle.get()) | 
| -    return; | 
| - | 
| -  const GenericTransferInfo& transfer = parameters_->transfer_info; | 
| +      GetDeviceHandle(parameters->handle); | 
| +  if (!device_handle.get()) { | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| +  } | 
|  | 
| +  const GenericTransferInfo& transfer = parameters->transfer_info; | 
| UsbEndpointDirection direction; | 
| size_t size = 0; | 
|  | 
| -  if (!ConvertDirectionSafely(transfer.direction, &direction)) { | 
| -    AsyncWorkCompleted(); | 
| -    return; | 
| +  if (!ConvertDirectionFromApi(transfer.direction, &direction)) { | 
| +    return RespondNow(Error(kErrorConvertDirection)); | 
| } | 
|  | 
| if (!GetTransferSize(transfer, &size)) { | 
| -    CompleteWithError(kErrorInvalidTransferLength); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidTransferLength)); | 
| } | 
|  | 
| scoped_refptr<net::IOBuffer> buffer = | 
| CreateBufferForTransfer(transfer, direction, size); | 
| if (!buffer.get()) { | 
| -    CompleteWithError(kErrorMalformedParameters); | 
| -    return; | 
| +    return RespondNow(Error(kErrorMalformedParameters)); | 
| } | 
|  | 
| int timeout = transfer.timeout ? *transfer.timeout : 0; | 
| if (timeout < 0) { | 
| -    CompleteWithError(kErrorInvalidTimeout); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidTimeout)); | 
| } | 
|  | 
| device_handle->BulkTransfer( | 
| direction, transfer.endpoint, buffer.get(), size, timeout, | 
| base::Bind(&UsbBulkTransferFunction::OnCompleted, this)); | 
| +  return RespondLater(); | 
| } | 
|  | 
| UsbInterruptTransferFunction::UsbInterruptTransferFunction() { | 
| @@ -1137,49 +1059,44 @@ UsbInterruptTransferFunction::UsbInterruptTransferFunction() { | 
| UsbInterruptTransferFunction::~UsbInterruptTransferFunction() { | 
| } | 
|  | 
| -bool UsbInterruptTransferFunction::Prepare() { | 
| -  parameters_ = InterruptTransfer::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbInterruptTransferFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::InterruptTransfer::Params> parameters = | 
| +      InterruptTransfer::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbInterruptTransferFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| -  if (!device_handle.get()) | 
| -    return; | 
| - | 
| -  const GenericTransferInfo& transfer = parameters_->transfer_info; | 
| +      GetDeviceHandle(parameters->handle); | 
| +  if (!device_handle.get()) { | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| +  } | 
|  | 
| +  const GenericTransferInfo& transfer = parameters->transfer_info; | 
| UsbEndpointDirection direction; | 
| size_t size = 0; | 
|  | 
| -  if (!ConvertDirectionSafely(transfer.direction, &direction)) { | 
| -    AsyncWorkCompleted(); | 
| -    return; | 
| +  if (!ConvertDirectionFromApi(transfer.direction, &direction)) { | 
| +    return RespondNow(Error(kErrorConvertDirection)); | 
| } | 
|  | 
| if (!GetTransferSize(transfer, &size)) { | 
| -    CompleteWithError(kErrorInvalidTransferLength); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidTransferLength)); | 
| } | 
|  | 
| scoped_refptr<net::IOBuffer> buffer = | 
| CreateBufferForTransfer(transfer, direction, size); | 
| if (!buffer.get()) { | 
| -    CompleteWithError(kErrorMalformedParameters); | 
| -    return; | 
| +    return RespondNow(Error(kErrorMalformedParameters)); | 
| } | 
|  | 
| int timeout = transfer.timeout ? *transfer.timeout : 0; | 
| if (timeout < 0) { | 
| -    CompleteWithError(kErrorInvalidTimeout); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidTimeout)); | 
| } | 
|  | 
| device_handle->InterruptTransfer( | 
| direction, transfer.endpoint, buffer.get(), size, timeout, | 
| base::Bind(&UsbInterruptTransferFunction::OnCompleted, this)); | 
| +  return RespondLater(); | 
| } | 
|  | 
| UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() { | 
| @@ -1188,66 +1105,62 @@ UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() { | 
| UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() { | 
| } | 
|  | 
| -bool UsbIsochronousTransferFunction::Prepare() { | 
| -  parameters_ = IsochronousTransfer::Params::Create(*args_); | 
| -  EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
| +ExtensionFunction::ResponseAction UsbIsochronousTransferFunction::Run() { | 
| +  scoped_ptr<extensions::core_api::usb::IsochronousTransfer::Params> | 
| +      parameters = IsochronousTransfer::Params::Create(*args_); | 
| +  EXTENSION_FUNCTION_VALIDATE(parameters.get()); | 
|  | 
| -void UsbIsochronousTransferFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| -  if (!device_handle.get()) | 
| -    return; | 
| +      GetDeviceHandle(parameters->handle); | 
| +  if (!device_handle.get()) { | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| +  } | 
|  | 
| -  const IsochronousTransferInfo& transfer = parameters_->transfer_info; | 
| +  const IsochronousTransferInfo& transfer = parameters->transfer_info; | 
| const GenericTransferInfo& generic_transfer = transfer.transfer_info; | 
| - | 
| size_t size = 0; | 
| UsbEndpointDirection direction; | 
|  | 
| -  if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) { | 
| -    AsyncWorkCompleted(); | 
| -    return; | 
| +  if (!ConvertDirectionFromApi(generic_transfer.direction, &direction)) { | 
| +    return RespondNow(Error(kErrorConvertDirection)); | 
| } | 
| + | 
| if (!GetTransferSize(generic_transfer, &size)) { | 
| -    CompleteWithError(kErrorInvalidTransferLength); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidTransferLength)); | 
| } | 
| + | 
| if (transfer.packets < 0 || transfer.packets >= kMaxPackets) { | 
| -    CompleteWithError(kErrorInvalidNumberOfPackets); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidNumberOfPackets)); | 
| } | 
| + | 
| unsigned int packets = transfer.packets; | 
| if (transfer.packet_length < 0 || | 
| transfer.packet_length >= kMaxPacketLength) { | 
| -    CompleteWithError(kErrorInvalidPacketLength); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidPacketLength)); | 
| } | 
| + | 
| unsigned int packet_length = transfer.packet_length; | 
| const uint64 total_length = packets * packet_length; | 
| if (packets > size || total_length > size) { | 
| -    CompleteWithError(kErrorTransferLength); | 
| -    return; | 
| +    return RespondNow(Error(kErrorTransferLength)); | 
| } | 
|  | 
| scoped_refptr<net::IOBuffer> buffer = | 
| CreateBufferForTransfer(generic_transfer, direction, size); | 
| if (!buffer.get()) { | 
| -    CompleteWithError(kErrorMalformedParameters); | 
| -    return; | 
| +    return RespondNow(Error(kErrorMalformedParameters)); | 
| } | 
|  | 
| int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0; | 
| if (timeout < 0) { | 
| -    CompleteWithError(kErrorInvalidTimeout); | 
| -    return; | 
| +    return RespondNow(Error(kErrorInvalidTimeout)); | 
| } | 
|  | 
| device_handle->IsochronousTransfer( | 
| direction, generic_transfer.endpoint, buffer.get(), size, packets, | 
| packet_length, timeout, | 
| base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this)); | 
| +  return RespondLater(); | 
| } | 
|  | 
| UsbResetDeviceFunction::UsbResetDeviceFunction() { | 
| @@ -1256,29 +1169,37 @@ UsbResetDeviceFunction::UsbResetDeviceFunction() { | 
| UsbResetDeviceFunction::~UsbResetDeviceFunction() { | 
| } | 
|  | 
| -bool UsbResetDeviceFunction::Prepare() { | 
| +ExtensionFunction::ResponseAction UsbResetDeviceFunction::Run() { | 
| parameters_ = ResetDevice::Params::Create(*args_); | 
| EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | 
| -  return true; | 
| -} | 
|  | 
| -void UsbResetDeviceFunction::AsyncWorkStart() { | 
| scoped_refptr<UsbDeviceHandle> device_handle = | 
| -      GetDeviceHandleOrCompleteWithError(parameters_->handle); | 
| -  if (!device_handle.get()) | 
| -    return; | 
| - | 
| -  bool success = device_handle->ResetDevice(); | 
| -  if (!success) { | 
| -    device_handle->Close(); | 
| -    RemoveUsbDeviceResource(parameters_->handle.handle); | 
| -    SetResult(new base::FundamentalValue(false)); | 
| -    CompleteWithError(kErrorResetDevice); | 
| -    return; | 
| +      GetDeviceHandle(parameters_->handle); | 
| +  if (!device_handle.get()) { | 
| +    return RespondNow(Error(kErrorNoConnection)); | 
| } | 
|  | 
| -  SetResult(new base::FundamentalValue(true)); | 
| -  AsyncWorkCompleted(); | 
| +  device_handle->ResetDevice( | 
| +      base::Bind(&UsbResetDeviceFunction::OnComplete, this)); | 
| +  return RespondLater(); | 
| +} | 
| + | 
| +void UsbResetDeviceFunction::OnComplete(bool success) { | 
| +  if (success) { | 
| +    Respond(OneArgument(new base::FundamentalValue(true))); | 
| +  } else { | 
| +    scoped_refptr<UsbDeviceHandle> device_handle = | 
| +        GetDeviceHandle(parameters_->handle); | 
| +    if (device_handle.get()) { | 
| +      device_handle->Close(); | 
| +    } | 
| +    ReleaseDeviceHandle(parameters_->handle); | 
| + | 
| +    scoped_ptr<base::ListValue> error_args(new base::ListValue()); | 
| +    error_args->AppendBoolean(false); | 
| +    // Returning arguments with an error is wrong but we're stuck with it. | 
| +    Respond(ErrorWithArguments(error_args.Pass(), kErrorResetDevice)); | 
| +  } | 
| } | 
|  | 
| }  // namespace extensions | 
|  |