| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/api_resource_controller.h" | 5 #include "chrome/browser/extensions/api/api_resource_controller.h" |
| 6 #include "chrome/browser/extensions/api/serial/serial_connection.h" | 6 #include "chrome/browser/extensions/api/serial/serial_connection.h" |
| 7 #include "chrome/browser/extensions/api/socket/socket.h" | 7 #include "chrome/browser/extensions/api/socket/socket.h" |
| 8 #include "chrome/browser/extensions/api/usb/usb_device_resource.h" | 8 #include "chrome/browser/extensions/api/usb/usb_device_resource.h" |
| 9 #include "content/public/browser/browser_thread.h" |
| 10 |
| 11 using content::BrowserThread; |
| 9 | 12 |
| 10 namespace extensions { | 13 namespace extensions { |
| 11 | 14 |
| 12 APIResourceController::APIResourceController() : next_api_resource_id_(1) {} | 15 APIResourceController::APIResourceController() |
| 16 : next_api_resource_id_(1), |
| 17 socket_resource_map_(new APIResourceMap), |
| 18 serial_connection_resource_map_(new APIResourceMap), |
| 19 usb_device_resource_map_(new APIResourceMap) {} |
| 13 | 20 |
| 14 APIResourceController::~APIResourceController() {} | 21 APIResourceController::~APIResourceController() { |
| 22 // If this check failed, then a unit test was using an APIResource but |
| 23 // didn't provide the IO/FILE thread message loops needed for those resources |
| 24 // to do their job (including destroying themselves at shutdown). |
| 25 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO)); |
| 26 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::FILE)); |
| 15 | 27 |
| 16 APIResource* APIResourceController::GetAPIResource(int api_resource_id) const { | 28 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, |
| 17 // TODO(miket): verify that the extension asking for the APIResource is the | 29 socket_resource_map_); |
| 18 // same one that created it. | 30 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE, |
| 19 APIResourceMap::const_iterator i = api_resource_map_.find(api_resource_id); | 31 serial_connection_resource_map_); |
| 20 if (i != api_resource_map_.end()) | 32 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, |
| 21 return i->second.get(); | 33 usb_device_resource_map_); |
| 22 return NULL; | 34 } |
| 35 |
| 36 APIResourceController::APIResourceMap* |
| 37 APIResourceController::GetResourceMapForType( |
| 38 APIResource::APIResourceType api_resource_type) const { |
| 39 switch (api_resource_type) { |
| 40 case APIResource::SocketResource: |
| 41 return socket_resource_map_; |
| 42 case APIResource::SerialConnectionResource: |
| 43 return serial_connection_resource_map_; |
| 44 case APIResource::UsbDeviceResource: |
| 45 return usb_device_resource_map_; |
| 46 default: |
| 47 NOTREACHED(); |
| 48 return NULL; |
| 49 } |
| 23 } | 50 } |
| 24 | 51 |
| 25 APIResource* APIResourceController::GetAPIResource( | 52 APIResource* APIResourceController::GetAPIResource( |
| 26 APIResource::APIResourceType api_resource_type, | 53 APIResource::APIResourceType api_resource_type, |
| 27 int api_resource_id) const { | 54 int api_resource_id) const { |
| 28 APIResource* resource = GetAPIResource(api_resource_id); | 55 // TODO(miket): verify that the extension asking for the APIResource is the |
| 56 // same one that created it. crbug.com/129675 |
| 57 APIResourceMap* map = GetResourceMapForType(api_resource_type); |
| 58 APIResourceMap::const_iterator i = map->find(api_resource_id); |
| 59 if (i == map->end()) |
| 60 return NULL; |
| 61 |
| 62 APIResource* resource = i->second.get(); |
| 29 | 63 |
| 30 // This DCHECK is going to catch some legitimate application-developer | 64 // This DCHECK is going to catch some legitimate application-developer |
| 31 // errors, where someone asks for resource of Type A with the wrong ID that | 65 // errors, where someone asks for resource of Type A with the wrong ID that |
| 32 // happens to belong to a resource of Type B. But in debug mode, it's more | 66 // happens to belong to a resource of Type B. But in debug mode, it's more |
| 33 // likely to catch a silly copy/paste coding error while developing a new | 67 // likely to catch a silly copy/paste coding error while developing a new |
| 34 // resource type, and unfortunately we can't really tell the difference. | 68 // resource type, and unfortunately we can't really tell the difference. |
| 35 // We'll choose the more informative outcome (loud explosion during debug) | 69 // We'll choose the more informative outcome (loud explosion during debug) |
| 36 // rather than a mysterious empty resource returned to JavaScript. | 70 // rather than a mysterious empty resource returned to JavaScript. |
| 37 DCHECK(!resource || resource->api_resource_type() == api_resource_type); | 71 DCHECK(!resource || resource->api_resource_type() == api_resource_type); |
| 38 | 72 |
| 39 if (resource && resource->api_resource_type() != api_resource_type) | 73 if (resource && resource->api_resource_type() != api_resource_type) |
| 40 resource = NULL; | 74 resource = NULL; |
| 41 | 75 |
| 42 return resource; | 76 return resource; |
| 43 } | 77 } |
| 44 | 78 |
| 45 int APIResourceController::AddAPIResource(APIResource* api_resource) { | 79 int APIResourceController::AddAPIResource(APIResource* api_resource) { |
| 80 APIResource::APIResourceType api_resource_type = |
| 81 api_resource->api_resource_type(); |
| 82 switch (api_resource_type) { |
| 83 case APIResource::SocketResource: |
| 84 case APIResource::UsbDeviceResource: |
| 85 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 86 break; |
| 87 case APIResource::SerialConnectionResource: |
| 88 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 89 break; |
| 90 default: |
| 91 NOTREACHED(); |
| 92 } |
| 93 APIResourceMap* map = GetResourceMapForType(api_resource_type); |
| 46 int id = GenerateAPIResourceId(); | 94 int id = GenerateAPIResourceId(); |
| 47 if (id > 0) { | 95 if (id > 0) { |
| 48 linked_ptr<APIResource> resource_ptr(api_resource); | 96 linked_ptr<APIResource> resource_ptr(api_resource); |
| 49 api_resource_map_[id] = resource_ptr; | 97 (*map)[id] = resource_ptr; |
| 50 return id; | 98 return id; |
| 51 } | 99 } |
| 52 return 0; | 100 return 0; |
| 53 } | 101 } |
| 54 | 102 |
| 55 bool APIResourceController::RemoveAPIResource(int api_resource_id) { | 103 bool APIResourceController::RemoveAPIResource( |
| 56 APIResource* api_resource = GetAPIResource(api_resource_id); | 104 APIResource::APIResourceType api_resource_type, int api_resource_id) { |
| 105 APIResource* api_resource = GetAPIResource(api_resource_type, |
| 106 api_resource_id); |
| 57 if (!api_resource) | 107 if (!api_resource) |
| 58 return false; | 108 return false; |
| 59 api_resource_map_.erase(api_resource_id); | 109 APIResourceMap* map = GetResourceMapForType( |
| 110 api_resource->api_resource_type()); |
| 111 map->erase(api_resource_id); |
| 60 return true; | 112 return true; |
| 61 } | 113 } |
| 62 | 114 |
| 115 bool APIResourceController::RemoveSocket(int api_resource_id) { |
| 116 return RemoveAPIResource(APIResource::SocketResource, api_resource_id); |
| 117 } |
| 118 |
| 119 bool APIResourceController::RemoveSerialConnection(int api_resource_id) { |
| 120 return RemoveAPIResource(APIResource::SerialConnectionResource, |
| 121 api_resource_id); |
| 122 } |
| 123 |
| 124 bool APIResourceController::RemoveUsbDeviceResource(int api_resource_id) { |
| 125 return RemoveAPIResource(APIResource::UsbDeviceResource, api_resource_id); |
| 126 } |
| 127 |
| 63 // TODO(miket): consider partitioning the ID space by extension ID | 128 // TODO(miket): consider partitioning the ID space by extension ID |
| 64 // to make it harder for extensions to peek into each others' resources. | 129 // to make it harder for extensions to peek into each others' resources. |
| 65 int APIResourceController::GenerateAPIResourceId() { | 130 int APIResourceController::GenerateAPIResourceId() { |
| 66 while (next_api_resource_id_ > 0 && | |
| 67 api_resource_map_.count(next_api_resource_id_) > 0) | |
| 68 ++next_api_resource_id_; | |
| 69 return next_api_resource_id_++; | 131 return next_api_resource_id_++; |
| 70 } | 132 } |
| 71 | 133 |
| 72 Socket* APIResourceController::GetSocket(int api_resource_id) const { | 134 Socket* APIResourceController::GetSocket(int api_resource_id) const { |
| 135 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 73 return static_cast<Socket*>(GetAPIResource(APIResource::SocketResource, | 136 return static_cast<Socket*>(GetAPIResource(APIResource::SocketResource, |
| 74 api_resource_id)); | 137 api_resource_id)); |
| 75 } | 138 } |
| 76 | 139 |
| 77 SerialConnection* APIResourceController::GetSerialConnection( | 140 SerialConnection* APIResourceController::GetSerialConnection( |
| 78 int api_resource_id) const { | 141 int api_resource_id) const { |
| 142 CHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 79 return static_cast<SerialConnection*>( | 143 return static_cast<SerialConnection*>( |
| 80 GetAPIResource(APIResource::SerialConnectionResource, api_resource_id)); | 144 GetAPIResource(APIResource::SerialConnectionResource, api_resource_id)); |
| 81 } | 145 } |
| 82 | 146 |
| 83 UsbDeviceResource* APIResourceController::GetUsbDeviceResource( | 147 UsbDeviceResource* APIResourceController::GetUsbDeviceResource( |
| 84 int api_resource_id) const { | 148 int api_resource_id) const { |
| 149 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 85 return static_cast<UsbDeviceResource*>(GetAPIResource( | 150 return static_cast<UsbDeviceResource*>(GetAPIResource( |
| 86 APIResource::UsbDeviceResource, api_resource_id)); | 151 APIResource::UsbDeviceResource, api_resource_id)); |
| 87 } | 152 } |
| 88 | 153 |
| 89 } // namespace extensions | 154 } // namespace extensions |
| OLD | NEW |