summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/api/api_function.cc38
-rw-r--r--chrome/browser/extensions/api/api_function.h19
-rw-r--r--chrome/browser/extensions/api/serial/serial_api.cc29
-rw-r--r--chrome/browser/extensions/api/serial/serial_api.h31
-rw-r--r--chrome/browser/extensions/api/serial/serial_connection.cc2
-rw-r--r--chrome/browser/extensions/api/serial/serial_connection.h4
-rw-r--r--chrome/browser/extensions/api/serial/serial_connection_posix.cc4
-rw-r--r--chrome/browser/extensions/api/socket/socket_api.h18
-rw-r--r--chrome/browser/extensions/api/usb/usb_api.h10
-rw-r--r--chrome/common/extensions/api/experimental.serial.idl9
-rw-r--r--chrome/test/data/extensions/api_test/serial/api/background.js22
11 files changed, 135 insertions, 51 deletions
diff --git a/chrome/browser/extensions/api/api_function.cc b/chrome/browser/extensions/api/api_function.cc
index 18f5320..6d24c66 100644
--- a/chrome/browser/extensions/api/api_function.cc
+++ b/chrome/browser/extensions/api/api_function.cc
@@ -9,13 +9,16 @@
#include "chrome/browser/extensions/api/api_resource_event_notifier.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
-#include "content/public/browser/browser_thread.h"
using content::BrowserThread;
namespace extensions {
-bool AsyncIOAPIFunction::RunImpl() {
+AsyncAPIFunction::AsyncAPIFunction()
+ : work_thread_id_(BrowserThread::IO) {
+}
+
+bool AsyncAPIFunction::RunImpl() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
extension_service_ = profile()->GetExtensionService();
@@ -23,42 +26,46 @@ bool AsyncIOAPIFunction::RunImpl() {
return false;
}
bool rv = BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&AsyncIOAPIFunction::WorkOnIOThread, this));
+ work_thread_id_, FROM_HERE,
+ base::Bind(&AsyncAPIFunction::WorkOnWorkThread, this));
DCHECK(rv);
return true;
}
-void AsyncIOAPIFunction::Work() {
+void AsyncAPIFunction::Work() {
}
-void AsyncIOAPIFunction::AsyncWorkStart() {
+void AsyncAPIFunction::AsyncWorkStart() {
Work();
AsyncWorkCompleted();
}
-void AsyncIOAPIFunction::AsyncWorkCompleted() {
+void AsyncAPIFunction::AsyncWorkCompleted() {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
bool rv = BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&AsyncIOAPIFunction::RespondOnUIThread, this));
+ base::Bind(&AsyncAPIFunction::RespondOnUIThread, this));
DCHECK(rv);
} else {
SendResponse(Respond());
}
}
-void AsyncIOAPIFunction::WorkOnIOThread() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+void AsyncAPIFunction::WorkOnWorkThread() {
+ DCHECK(BrowserThread::CurrentlyOn(work_thread_id_));
+ DCHECK(work_thread_id_ != BrowserThread::UI) <<
+ "You have specified that AsyncAPIFunction::Work() should happen on "
+ "the UI thread. This nullifies the point of this class. Either "
+ "specify a different thread or derive from a different class.";
AsyncWorkStart();
}
-void AsyncIOAPIFunction::RespondOnUIThread() {
+void AsyncAPIFunction::RespondOnUIThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
SendResponse(Respond());
}
-int AsyncIOAPIFunction::ExtractSrcId(size_t argument_position) {
+int AsyncAPIFunction::ExtractSrcId(size_t argument_position) {
scoped_ptr<DictionaryValue> options(new DictionaryValue());
if (args_->GetSize() > argument_position) {
DictionaryValue* temp_options = NULL;
@@ -76,17 +83,16 @@ int AsyncIOAPIFunction::ExtractSrcId(size_t argument_position) {
return src_id;
}
-APIResourceEventNotifier* AsyncIOAPIFunction::CreateEventNotifier(int src_id) {
+APIResourceEventNotifier* AsyncAPIFunction::CreateEventNotifier(int src_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
return new APIResourceEventNotifier(
profile()->GetExtensionEventRouter(), profile(), extension_id(),
src_id, source_url());
}
-APIResourceController* AsyncIOAPIFunction::controller() {
+APIResourceController* AsyncAPIFunction::controller() {
// ExtensionService's APIResourceController is set exactly once, long before
- // this code is reached, so it's safe to access it on either the IO or UI
- // thread.
+ // this code is reached, so it's safe to access it on any thread.
return extension_service_->api_resource_controller();
}
diff --git a/chrome/browser/extensions/api/api_function.h b/chrome/browser/extensions/api/api_function.h
index 229d1c5..ad48a2d 100644
--- a/chrome/browser/extensions/api/api_function.h
+++ b/chrome/browser/extensions/api/api_function.h
@@ -8,6 +8,7 @@
#include "chrome/browser/extensions/extension_function.h"
#include "chrome/browser/extensions/api/api_resource.h"
+#include "content/public/browser/browser_thread.h"
class ExtensionService;
@@ -16,11 +17,12 @@ namespace extensions {
class APIResourceController;
class APIResourceEventNotifier;
-// AsyncIOAPIFunction provides convenient thread management for APIs that
-// need to do essentially all their work on the IO thread.
-class AsyncIOAPIFunction : public AsyncExtensionFunction {
+// AsyncAPIFunction provides convenient thread management for APIs that need to
+// do essentially all their work on the IO or FILE thread.
+class AsyncAPIFunction : public AsyncExtensionFunction {
protected:
- virtual ~AsyncIOAPIFunction() {}
+ AsyncAPIFunction();
+ virtual ~AsyncAPIFunction() {}
// Set up for work (e.g., validate arguments). Guaranteed to happen on UI
// thread.
@@ -48,11 +50,16 @@ class AsyncIOAPIFunction : public AsyncExtensionFunction {
// Access to the controller singleton.
APIResourceController* controller();
- // ExtensionFunction:
+ // ExtensionFunction::RunImpl()
virtual bool RunImpl() OVERRIDE;
+ protected:
+ // If you don't want your Work() method to happen on the IO thread, then set
+ // this to the thread that you do want, preferably in Prepare().
+ content::BrowserThread::ID work_thread_id_;
+
private:
- void WorkOnIOThread();
+ void WorkOnWorkThread();
void RespondOnUIThread();
ExtensionService* extension_service_;
diff --git a/chrome/browser/extensions/api/serial/serial_api.cc b/chrome/browser/extensions/api/serial/serial_api.cc
index e25b8cf..93855f2 100644
--- a/chrome/browser/extensions/api/serial/serial_api.cc
+++ b/chrome/browser/extensions/api/serial/serial_api.cc
@@ -9,14 +9,43 @@
#include "base/values.h"
#include "chrome/browser/extensions/api/api_resource_controller.h"
#include "chrome/browser/extensions/api/serial/serial_connection.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
namespace extensions {
const char kConnectionIdKey[] = "connectionId";
+const char kPortsKey[] = "ports";
const char kDataKey[] = "data";
const char kBytesReadKey[] = "bytesRead";
const char kBytesWrittenKey[] = "bytesWritten";
+SerialGetPortsFunction::SerialGetPortsFunction() {}
+
+bool SerialGetPortsFunction::Prepare() {
+ work_thread_id_ = BrowserThread::FILE;
+ return true;
+}
+
+void SerialGetPortsFunction::Work() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
+ ListValue* ports = new ListValue();
+ SerialConnection::StringSet port_names =
+ SerialConnection::GenerateValidSerialPortNames();
+ SerialConnection::StringSet::const_iterator i = port_names.begin();
+ while (i != port_names.end()) {
+ ports->Append(Value::CreateStringValue(*i++));
+ }
+
+ result_.reset(ports);
+}
+
+bool SerialGetPortsFunction::Respond() {
+ return true;
+}
+
SerialOpenFunction::SerialOpenFunction() : src_id_(-1) {}
bool SerialOpenFunction::Prepare() {
diff --git a/chrome/browser/extensions/api/serial/serial_api.h b/chrome/browser/extensions/api/serial/serial_api.h
index 902d641..7965d87 100644
--- a/chrome/browser/extensions/api/serial/serial_api.h
+++ b/chrome/browser/extensions/api/serial/serial_api.h
@@ -16,7 +16,22 @@ namespace extensions {
extern const char kConnectionIdKey[];
-class SerialOpenFunction : public AsyncIOAPIFunction {
+class SerialGetPortsFunction : public AsyncAPIFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION_NAME("experimental.serial.getPorts")
+
+ SerialGetPortsFunction();
+
+ protected:
+ virtual ~SerialGetPortsFunction() {}
+
+ // AsyncAPIFunction:
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+ virtual bool Respond() OVERRIDE;
+};
+
+class SerialOpenFunction : public AsyncAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION_NAME("experimental.serial.open")
@@ -25,7 +40,7 @@ class SerialOpenFunction : public AsyncIOAPIFunction {
protected:
virtual ~SerialOpenFunction() {}
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void Work() OVERRIDE;
virtual bool Respond() OVERRIDE;
@@ -35,14 +50,14 @@ class SerialOpenFunction : public AsyncIOAPIFunction {
std::string port_;
};
-class SerialCloseFunction : public AsyncIOAPIFunction {
+class SerialCloseFunction : public AsyncAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION_NAME("experimental.serial.close")
protected:
virtual ~SerialCloseFunction() {}
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void Work() OVERRIDE;
virtual bool Respond() OVERRIDE;
@@ -51,14 +66,14 @@ class SerialCloseFunction : public AsyncIOAPIFunction {
int connection_id_;
};
-class SerialReadFunction : public AsyncIOAPIFunction {
+class SerialReadFunction : public AsyncAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION_NAME("experimental.serial.read")
protected:
virtual ~SerialReadFunction() {}
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void Work() OVERRIDE;
virtual bool Respond() OVERRIDE;
@@ -67,7 +82,7 @@ class SerialReadFunction : public AsyncIOAPIFunction {
int connection_id_;
};
-class SerialWriteFunction : public AsyncIOAPIFunction {
+class SerialWriteFunction : public AsyncAPIFunction {
public:
DECLARE_EXTENSION_FUNCTION_NAME("experimental.serial.write")
@@ -76,7 +91,7 @@ class SerialWriteFunction : public AsyncIOAPIFunction {
protected:
virtual ~SerialWriteFunction();
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void Work() OVERRIDE;
virtual bool Respond() OVERRIDE;
diff --git a/chrome/browser/extensions/api/serial/serial_connection.cc b/chrome/browser/extensions/api/serial/serial_connection.cc
index ed9314b..d17a707 100644
--- a/chrome/browser/extensions/api/serial/serial_connection.cc
+++ b/chrome/browser/extensions/api/serial/serial_connection.cc
@@ -8,7 +8,7 @@
namespace extensions {
-const char kSerialConnectionNotFoundError[] = "Serial conenction not found";
+const char kSerialConnectionNotFoundError[] = "Serial connection not found";
// static
bool SerialConnection::DoesPortExist(const StringSet& name_set,
diff --git a/chrome/browser/extensions/api/serial/serial_connection.h b/chrome/browser/extensions/api/serial/serial_connection.h
index d62189d..7dca2aa 100644
--- a/chrome/browser/extensions/api/serial/serial_connection.h
+++ b/chrome/browser/extensions/api/serial/serial_connection.h
@@ -44,11 +44,9 @@ class SerialConnection : public APIResource {
static bool DoesPortExist(const StringSet& port_patterns,
const std::string& port_name);
- private:
- // TODO(miket): expose this functionality via API. Otherwise developers have
- // to guess at valid names.
static StringSet GenerateValidSerialPortNames();
+ private:
// Returns a StringSet of patterns to be used with MatchPattern.
static StringSet GenerateValidPatterns();
diff --git a/chrome/browser/extensions/api/serial/serial_connection_posix.cc b/chrome/browser/extensions/api/serial/serial_connection_posix.cc
index 4e1fa5d..8e6e567 100644
--- a/chrome/browser/extensions/api/serial/serial_connection_posix.cc
+++ b/chrome/browser/extensions/api/serial/serial_connection_posix.cc
@@ -14,6 +14,9 @@
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/string_util.h"
+#include "content/public/browser/browser_thread.h"
+
+using content::BrowserThread;
namespace extensions {
@@ -105,6 +108,7 @@ SerialConnection::StringSet SerialConnection::GenerateValidPatterns() {
// TODO(miket): this might be refactorable into serial_connection.cc, if
// Windows serial-port enumeration also entails looking through a directory.
SerialConnection::StringSet SerialConnection::GenerateValidSerialPortNames() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
const FilePath DEV_ROOT("/dev");
const file_util::FileEnumerator::FileType FILES_AND_SYM_LINKS =
static_cast<file_util::FileEnumerator::FileType>(
diff --git a/chrome/browser/extensions/api/socket/socket_api.h b/chrome/browser/extensions/api/socket/socket_api.h
index 4ed01df..f919708 100644
--- a/chrome/browser/extensions/api/socket/socket_api.h
+++ b/chrome/browser/extensions/api/socket/socket_api.h
@@ -21,7 +21,7 @@ extern const char kBytesWrittenKey[];
extern const char kSocketIdKey[];
extern const char kUdpSocketType[];
-class SocketExtensionFunction : public AsyncIOAPIFunction {
+class SocketExtensionFunction : public AsyncAPIFunction {
public:
virtual void Work() OVERRIDE;
virtual bool Respond() OVERRIDE;
@@ -42,7 +42,7 @@ class SocketCreateFunction : public SocketExtensionFunction {
protected:
virtual ~SocketCreateFunction();
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void Work() OVERRIDE;
@@ -65,7 +65,7 @@ class SocketDestroyFunction : public SocketExtensionFunction {
protected:
virtual ~SocketDestroyFunction() {}
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void Work() OVERRIDE;
@@ -82,7 +82,7 @@ class SocketConnectFunction : public SocketExtensionFunction {
protected:
virtual ~SocketConnectFunction() {}
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void AsyncWorkStart() OVERRIDE;
@@ -99,7 +99,7 @@ class SocketDisconnectFunction : public SocketExtensionFunction {
protected:
virtual ~SocketDisconnectFunction() {}
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void Work() OVERRIDE;
@@ -129,7 +129,7 @@ class SocketReadFunction : public SocketExtensionFunction {
protected:
virtual ~SocketReadFunction() {}
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void AsyncWorkStart() OVERRIDE;
@@ -147,7 +147,7 @@ class SocketWriteFunction : public SocketExtensionFunction {
protected:
virtual ~SocketWriteFunction();
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void AsyncWorkStart() OVERRIDE;
@@ -168,7 +168,7 @@ class SocketRecvFromFunction : public SocketExtensionFunction {
protected:
virtual ~SocketRecvFromFunction();
- // AsyncIOAPIFunction
+ // AsyncAPIFunction
virtual bool Prepare() OVERRIDE;
virtual void AsyncWorkStart() OVERRIDE;
@@ -186,7 +186,7 @@ class SocketSendToFunction : public SocketExtensionFunction {
virtual ~SocketSendToFunction();
void OnCompleted(int result);
- // AsyncIOAPIFunction:
+ // AsyncAPIFunction:
virtual bool Prepare() OVERRIDE;
virtual void AsyncWorkStart() OVERRIDE;
diff --git a/chrome/browser/extensions/api/usb/usb_api.h b/chrome/browser/extensions/api/usb/usb_api.h
index b182f65..402eb9b 100644
--- a/chrome/browser/extensions/api/usb/usb_api.h
+++ b/chrome/browser/extensions/api/usb/usb_api.h
@@ -15,7 +15,7 @@ namespace extensions {
class APIResourceEventNotifier;
-class UsbFindDeviceFunction : public AsyncIOAPIFunction {
+class UsbFindDeviceFunction : public AsyncAPIFunction {
public:
UsbFindDeviceFunction();
virtual ~UsbFindDeviceFunction();
@@ -32,7 +32,7 @@ class UsbFindDeviceFunction : public AsyncIOAPIFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.usb.findDevice");
};
-class UsbCloseDeviceFunction : public AsyncIOAPIFunction {
+class UsbCloseDeviceFunction : public AsyncAPIFunction {
public:
UsbCloseDeviceFunction();
virtual ~UsbCloseDeviceFunction();
@@ -49,7 +49,7 @@ class UsbCloseDeviceFunction : public AsyncIOAPIFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.usb.closeDevice");
};
-class UsbControlTransferFunction : public AsyncIOAPIFunction {
+class UsbControlTransferFunction : public AsyncAPIFunction {
public:
UsbControlTransferFunction();
virtual ~UsbControlTransferFunction();
@@ -66,7 +66,7 @@ class UsbControlTransferFunction : public AsyncIOAPIFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.usb.controlTransfer");
};
-class UsbBulkTransferFunction : public AsyncIOAPIFunction {
+class UsbBulkTransferFunction : public AsyncAPIFunction {
public:
UsbBulkTransferFunction();
virtual ~UsbBulkTransferFunction();
@@ -83,7 +83,7 @@ class UsbBulkTransferFunction : public AsyncIOAPIFunction {
DECLARE_EXTENSION_FUNCTION_NAME("experimental.usb.bulkTransfer");
};
-class UsbInterruptTransferFunction : public AsyncIOAPIFunction {
+class UsbInterruptTransferFunction : public AsyncAPIFunction {
public:
UsbInterruptTransferFunction();
virtual ~UsbInterruptTransferFunction();
diff --git a/chrome/common/extensions/api/experimental.serial.idl b/chrome/common/extensions/api/experimental.serial.idl
index ebc6c06..dab96431 100644
--- a/chrome/common/extensions/api/experimental.serial.idl
+++ b/chrome/common/extensions/api/experimental.serial.idl
@@ -6,6 +6,8 @@
[nodoc] namespace experimental.serial {
+ callback GetPortsCallback = void (DOMString[] ports);
+
dictionary OpenInfo {
// The id of the opened connection.
long connectionId;
@@ -35,6 +37,13 @@
callback WriteCallback = void (WriteInfo writeInfo);
interface Functions {
+ // Returns names of valid ports on this machine, each of which is likely to
+ // be valid to pass as the port argument to open(). The list is regenerated
+ // each time this method is called, as port validity is dynamic.
+ //
+ // |callback| : Called with the list of ports.
+ static void getPorts(GetPortsCallback callback);
+
// Opens a connection to the given serial port.
// |port| : The name of the serial port to open.
// |callback| : Called when the connection has been opened.
diff --git a/chrome/test/data/extensions/api_test/serial/api/background.js b/chrome/test/data/extensions/api_test/serial/api/background.js
index 60d62bb..7bb35da 100644
--- a/chrome/test/data/extensions/api_test/serial/api/background.js
+++ b/chrome/test/data/extensions/api_test/serial/api/background.js
@@ -32,11 +32,27 @@ var testSerial = function() {
chrome.experimental.serial.open(serialPort, onOpen);
};
+var testGetPorts = function() {
+ var onGetPorts = function(ports) {
+ // Any length is potentially valid, because we're on unknown hardware. But
+ // we are testing at least that the ports member was filled in, so it's
+ // still a somewhat meaningful test.
+ chrome.test.assertTrue(ports.length >= 0);
+ chrome.test.succeed();
+ }
+
+ chrome.experimental.serial.getPorts(onGetPorts);
+};
+
var onMessageReply = function(message) {
serialPort = message;
- if (message == 'none') {
- chrome.test.runTests([]);
- } else {
+ var generalTests = [ testGetPorts ];
+
+ chrome.test.runTests(generalTests);
+ if (message != 'none') {
+ // We have a specific serial port set up to respond to test traffic. This
+ // is a rare situation. TODO(miket): mock to make it testable under any
+ // hardware conditions.
chrome.test.runTests([ testSerial ]);
}
};