| Index: chrome/browser/extensions/api/socket/socket_api_controller.cc
|
| diff --git a/chrome/browser/extensions/api/socket/socket_api_controller.cc b/chrome/browser/extensions/api/socket/socket_api_controller.cc
|
| index 30e3a3ae71f5667cd5c2a812734a5d3476738ef3..8d00c14c2e531ac5832d11c75df50cc468e87174 100644
|
| --- a/chrome/browser/extensions/api/socket/socket_api_controller.cc
|
| +++ b/chrome/browser/extensions/api/socket/socket_api_controller.cc
|
| @@ -6,6 +6,7 @@
|
| #include "base/stl_util.h"
|
| #include "base/values.h"
|
| #include "chrome/browser/extensions/api/socket/socket_api_controller.h"
|
| +#include "chrome/browser/extensions/extension_event_router.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| #include "net/base/io_buffer.h"
|
| #include "net/base/net_errors.h"
|
| @@ -16,13 +17,39 @@
|
|
|
| using namespace net;
|
|
|
| +namespace events {
|
| +const char kOnEvent[] = "experimental.socket.onEvent";
|
| +}; // namespace events
|
| +
|
| namespace extensions {
|
|
|
| +enum SocketEventType {
|
| + SOCKET_EVENT_WRITE_COMPLETE
|
| +};
|
| +
|
| +const char kEventTypeKey[] = "type";
|
| +const char kEventTypeWriteComplete[] = "writeComplete";
|
| +
|
| +const char kSrcIdKey[] = "srcId";
|
| +const char kIsFinalEventKey[] = "isFinalEvent";
|
| +
|
| +const char kResultCodeKey[] = "resultCode";
|
| +
|
| +std::string SocketEventTypeToString(SocketEventType event_type) {
|
| + switch (event_type) {
|
| + case SOCKET_EVENT_WRITE_COMPLETE:
|
| + return kEventTypeWriteComplete;
|
| + default:
|
| + NOTREACHED();
|
| + return std::string();
|
| + }
|
| +}
|
| +
|
| // A Socket wraps a low-level socket and includes housekeeping information that
|
| // we need to manage it in the context of an extension.
|
| class Socket {
|
| public:
|
| - Socket(const Profile* profile, const std::string& src_extension_id,
|
| + Socket(Profile* profile, const std::string& src_extension_id, int src_id,
|
| const GURL& src_url);
|
| ~Socket();
|
|
|
| @@ -30,25 +57,29 @@ class Socket {
|
| void Close();
|
| int Write(const std::string message);
|
|
|
| + void OnSocketEvent(SocketEventType event_type, int result_code);
|
| +
|
| private:
|
| - // TODO(miket): this metadata will enable us to pass events back to the
|
| - // extension that created this Socket.
|
| - const Profile* profile_;
|
| int id_;
|
| +
|
| + // This group of variables lets us send events back to the creator extension.
|
| + Profile* profile_;
|
| std::string src_extension_id_;
|
| + int src_id_;
|
| GURL src_url_;
|
|
|
| scoped_ptr<net::UDPClientSocket> udp_client_socket_;
|
| bool is_connected_;
|
|
|
| - // A callback required by UDPClientSocket::Write().
|
| - void OnIOComplete(int result);
|
| + void OnWriteComplete(int result);
|
| };
|
|
|
| -Socket::Socket(const Profile* profile, const std::string& src_extension_id,
|
| - const GURL& src_url)
|
| - : profile_(profile),
|
| +Socket::Socket(Profile* profile, const std::string& src_extension_id,
|
| + int src_id, const GURL& src_url)
|
| + : id_(-1),
|
| + profile_(profile),
|
| src_extension_id_(src_extension_id),
|
| + src_id_(src_id),
|
| src_url_(src_url),
|
| udp_client_socket_(new UDPClientSocket(
|
| DatagramSocket::DEFAULT_BIND,
|
| @@ -63,8 +94,36 @@ Socket::~Socket() {
|
| }
|
| }
|
|
|
| -void Socket::OnIOComplete(int result) {
|
| - // We don't need to do anything.
|
| +void Socket::OnSocketEvent(SocketEventType event_type, int result_code) {
|
| + // Do we have a destination for this event?
|
| + if (src_id_ < 0)
|
| + return;
|
| +
|
| + std::string event_type_string = SocketEventTypeToString(event_type);
|
| +
|
| + ListValue args;
|
| + DictionaryValue* event = new DictionaryValue();
|
| + event->SetString(kEventTypeKey, event_type_string);
|
| + event->SetInteger(kSrcIdKey, src_id_);
|
| +
|
| + // TODO(miket): Signal that it's OK to clean up onEvent listeners. This is
|
| + // the framework we'll use, but we need to start using it.
|
| + event->SetBoolean(kIsFinalEventKey, false);
|
| +
|
| + if (event_type == SOCKET_EVENT_WRITE_COMPLETE) {
|
| + event->SetInteger(kResultCodeKey, result_code);
|
| + }
|
| +
|
| + args.Set(0, event);
|
| + std::string json_args;
|
| + base::JSONWriter::Write(&args, false, &json_args);
|
| +
|
| + profile_->GetExtensionEventRouter()->DispatchEventToExtension(
|
| + src_extension_id_,
|
| + events::kOnEvent,
|
| + json_args,
|
| + profile_,
|
| + src_url_);
|
| }
|
|
|
| bool Socket::Connect(const net::IPEndPoint& ip_end_point) {
|
| @@ -77,6 +136,10 @@ void Socket::Close() {
|
| udp_client_socket_->Close();
|
| }
|
|
|
| +void Socket::OnWriteComplete(int result) {
|
| + OnSocketEvent(SOCKET_EVENT_WRITE_COMPLETE, result);
|
| +}
|
| +
|
| int Socket::Write(const std::string message) {
|
| int length = message.length();
|
| scoped_refptr<StringIOBuffer> io_buffer(new StringIOBuffer(message));
|
| @@ -87,7 +150,7 @@ int Socket::Write(const std::string message) {
|
| while (buffer->BytesRemaining()) {
|
| int rv = udp_client_socket_->Write(
|
| buffer, buffer->BytesRemaining(),
|
| - base::Bind(&Socket::OnIOComplete, base::Unretained(this)));
|
| + base::Bind(&Socket::OnWriteComplete, base::Unretained(this)));
|
| if (rv <= 0) {
|
| // We pass all errors, including ERROR_IO_PENDING, back to the caller.
|
| return bytes_sent > 0 ? bytes_sent : rv;
|
| @@ -112,10 +175,12 @@ Socket* SocketController::GetSocket(int socket_id) {
|
| return NULL;
|
| }
|
|
|
| -int SocketController::CreateUdp(const Profile* profile,
|
| +int SocketController::CreateUdp(Profile* profile,
|
| const std::string& extension_id,
|
| + int src_id,
|
| const GURL& src_url) {
|
| - linked_ptr<Socket> socket(new Socket(profile, extension_id, src_url));
|
| + linked_ptr<Socket> socket(new Socket(profile, extension_id, src_id,
|
| + src_url));
|
| CHECK(socket.get());
|
| socket_map_[next_socket_id_] = socket;
|
| return next_socket_id_++;
|
|
|