0

Added JsonMessage to the control channel.

This adds the client plumbing needed to get an arbitrary JSON message from client to host, or vice versa. This will allow us to extend the protocol at short notice, without needing to wait for client plugin changes to be promoted to Stable.

BUG=

Review URL: https://chromiumcodereview.appspot.com/22477006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217127 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
jamiewalch@chromium.org
2013-08-13 00:13:48 +00:00
parent 3570ac4e04
commit 09eabd65c6
20 changed files with 125 additions and 2 deletions

@@ -119,6 +119,13 @@ void ChromotingClient::SetPairingResponse(
user_interface_->SetPairingResponse(pairing_response);
}
void ChromotingClient::DeliverHostMessage(
const protocol::ExtensionMessage& message) {
DCHECK(task_runner_->BelongsToCurrentThread());
user_interface_->DeliverHostMessage(message);
}
void ChromotingClient::InjectClipboardEvent(
const protocol::ClipboardEvent& event) {
DCHECK(task_runner_->BelongsToCurrentThread());

@@ -67,6 +67,8 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
const protocol::Capabilities& capabilities) OVERRIDE;
virtual void SetPairingResponse(
const protocol::PairingResponse& pairing_response) OVERRIDE;
virtual void DeliverHostMessage(
const protocol::ExtensionMessage& message) OVERRIDE;
// ClipboardStub implementation for receiving clipboard data from host.
virtual void InjectClipboardEvent(

@@ -42,6 +42,10 @@ class ClientUserInterface {
virtual void SetPairingResponse(
const protocol::PairingResponse& pairing_response) = 0;
// Deliver an extension message from the host to the client.
virtual void DeliverHostMessage(
const protocol::ExtensionMessage& message) = 0;
// Get the view's ClipboardStub implementation.
virtual protocol::ClipboardStub* GetClipboardStub() = 0;

@@ -176,6 +176,11 @@ void ChromotingJniInstance::SetPairingResponse(
response.shared_secret()));
}
void ChromotingJniInstance::DeliverHostMessage(
const protocol::ExtensionMessage& message) {
NOTIMPLEMENTED();
}
protocol::ClipboardStub* ChromotingJniInstance::GetClipboardStub() {
return this;
}

@@ -78,6 +78,8 @@ class ChromotingJniInstance
virtual void SetCapabilities(const std::string& capabilities) OVERRIDE;
virtual void SetPairingResponse(
const protocol::PairingResponse& response) OVERRIDE;
virtual void DeliverHostMessage(
const protocol::ExtensionMessage& message) OVERRIDE;
virtual protocol::ClipboardStub* GetClipboardStub() OVERRIDE;
virtual protocol::CursorShapeStub* GetCursorShapeStub() OVERRIDE;
virtual scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>

@@ -144,7 +144,7 @@ logging::LogMessageHandlerFunction g_logging_old_handler = NULL;
const char ChromotingInstance::kApiFeatures[] =
"highQualityScaling injectKeyEvent sendClipboardItem remapKey trapKey "
"notifyClientDimensions notifyClientResolution pauseVideo pauseAudio "
"asyncPin thirdPartyAuth pinlessAuth";
"asyncPin thirdPartyAuth pinlessAuth extensionMessage";
const char ChromotingInstance::kRequestedCapabilities[] = "";
const char ChromotingInstance::kSupportedCapabilities[] = "desktopShape";
@@ -433,6 +433,13 @@ void ChromotingInstance::HandleMessage(const pp::Var& message) {
return;
}
RequestPairing(client_name);
} else if (method == "extensionMessage") {
std::string type, message;
if (!data->GetString("type", &type) || !data->GetString("data", &message)) {
LOG(ERROR) << "Invalid extensionMessage.";
return;
}
SendClientMessage(type, message);
}
}
@@ -537,6 +544,14 @@ void ChromotingInstance::SetPairingResponse(
PostChromotingMessage("pairingResponse", data.Pass());
}
void ChromotingInstance::DeliverHostMessage(
const protocol::ExtensionMessage& message) {
scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
data->SetString("type", message.type());
data->SetString("data", message.data());
PostChromotingMessage("extensionMessage", data.Pass());
}
void ChromotingInstance::FetchSecretFromDialog(
bool pairing_supported,
const protocol::SecretFetchedCallback& secret_fetched_callback) {
@@ -839,6 +854,17 @@ void ChromotingInstance::RequestPairing(const std::string& client_name) {
host_connection_->host_stub()->RequestPairing(pairing_request);
}
void ChromotingInstance::SendClientMessage(const std::string& type,
const std::string& data) {
if (!IsConnected()) {
return;
}
protocol::ExtensionMessage message;
message.set_type(type);
message.set_data(data);
host_connection_->host_stub()->DeliverClientMessage(message);
}
ChromotingStats* ChromotingInstance::GetStats() {
if (!client_.get())
return NULL;

@@ -120,6 +120,8 @@ class ChromotingInstance :
virtual void SetCapabilities(const std::string& capabilities) OVERRIDE;
virtual void SetPairingResponse(
const protocol::PairingResponse& pairing_response) OVERRIDE;
virtual void DeliverHostMessage(
const protocol::ExtensionMessage& message) OVERRIDE;
virtual protocol::ClipboardStub* GetClipboardStub() OVERRIDE;
virtual protocol::CursorShapeStub* GetCursorShapeStub() OVERRIDE;
virtual scoped_ptr<protocol::ThirdPartyClientAuthenticator::TokenFetcher>
@@ -198,6 +200,7 @@ class ChromotingInstance :
void OnThirdPartyTokenFetched(const std::string& token,
const std::string& shared_secret);
void RequestPairing(const std::string& client_name);
void SendClientMessage(const std::string& type, const std::string& data);
// Helper method to post messages to the webapp.
void PostChromotingMessage(const std::string& method,

@@ -187,6 +187,13 @@ void ClientSession::RequestPairing(
}
}
void ClientSession::DeliverClientMessage(
const protocol::ExtensionMessage& message) {
// No messages are currently supported.
LOG(INFO) << "Unexpected message received: "
<< message.type() << ": " << message.data();
}
void ClientSession::OnConnectionAuthenticated(
protocol::ConnectionToClient* connection) {
DCHECK(CalledOnValidThread());

@@ -111,6 +111,8 @@ class ClientSession
const protocol::Capabilities& capabilities) OVERRIDE;
virtual void RequestPairing(
const remoting::protocol::PairingRequest& pairing_request) OVERRIDE;
virtual void DeliverClientMessage(
const protocol::ExtensionMessage& message) OVERRIDE;
// protocol::ConnectionToClient::EventHandler interface.
virtual void OnConnectionAuthenticated(

@@ -66,3 +66,14 @@ message PairingResponse {
// Shared secret for this client.
optional string shared_secret = 2;
}
message ExtensionMessage {
// The message type. This is used to dispatch the message to the correct
// recipient.
optional string type = 1;
// String-encoded message data. The client and host must agree on the encoding
// for each message type; different message types need not shared the same
// encoding.
optional string data = 2;
}

@@ -24,6 +24,7 @@ message ControlMessage {
optional Capabilities capabilities = 6;
optional PairingRequest pairing_request = 7;
optional PairingResponse pairing_response = 8;
optional ExtensionMessage extension_message = 9;
}
// Defines an event message on the event channel.

@@ -74,6 +74,13 @@ void ClientControlDispatcher::RequestPairing(
writer_.Write(SerializeAndFrameMessage(message), base::Closure());
}
void ClientControlDispatcher::DeliverClientMessage(
const ExtensionMessage& message) {
ControlMessage control_message;
control_message.mutable_extension_message()->CopyFrom(message);
writer_.Write(SerializeAndFrameMessage(control_message), base::Closure());
}
void ClientControlDispatcher::OnMessageReceived(
scoped_ptr<ControlMessage> message, const base::Closure& done_task) {
DCHECK(client_stub_);
@@ -88,6 +95,8 @@ void ClientControlDispatcher::OnMessageReceived(
client_stub_->SetCursorShape(message->cursor_shape());
} else if (message->has_pairing_response()) {
client_stub_->SetPairingResponse(message->pairing_response());
} else if (message->has_extension_message()) {
client_stub_->DeliverHostMessage(message->extension_message());
} else {
LOG(WARNING) << "Unknown control message received.";
}

@@ -40,6 +40,7 @@ class ClientControlDispatcher : public ChannelDispatcherBase,
virtual void ControlAudio(const AudioControl& audio_control) OVERRIDE;
virtual void SetCapabilities(const Capabilities& capabilities) OVERRIDE;
virtual void RequestPairing(const PairingRequest& pairing_request) OVERRIDE;
virtual void DeliverClientMessage(const ExtensionMessage& message) OVERRIDE;
// Sets the ClientStub that will be called for each incoming control
// message. |client_stub| must outlive this object.

@@ -18,6 +18,7 @@ namespace remoting {
namespace protocol {
class Capabilities;
class ExtensionMessage;
class PairingResponse;
class ClientStub : public ClipboardStub,
@@ -32,6 +33,9 @@ class ClientStub : public ClipboardStub,
// Passes a pairing response message to the client.
virtual void SetPairingResponse(const PairingResponse& pairing_response) = 0;
// Deliver an extension message from the host to the client.
virtual void DeliverHostMessage(const ExtensionMessage& message) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(ClientStub);
};

@@ -46,6 +46,13 @@ void HostControlDispatcher::SetPairingResponse(
writer_.Write(SerializeAndFrameMessage(message), base::Closure());
}
void HostControlDispatcher::DeliverHostMessage(
const ExtensionMessage& message) {
ControlMessage control_message;
control_message.mutable_extension_message()->CopyFrom(message);
writer_.Write(SerializeAndFrameMessage(control_message), base::Closure());
}
void HostControlDispatcher::InjectClipboardEvent(const ClipboardEvent& event) {
ControlMessage message;
message.mutable_clipboard_event()->CopyFrom(event);
@@ -78,6 +85,8 @@ void HostControlDispatcher::OnMessageReceived(
host_stub_->SetCapabilities(message->capabilities());
} else if (message->has_pairing_request()) {
host_stub_->RequestPairing(message->pairing_request());
} else if (message->has_extension_message()) {
host_stub_->DeliverClientMessage(message->extension_message());
} else {
LOG(WARNING) << "Unknown control message received.";
}

@@ -37,6 +37,8 @@ class HostControlDispatcher : public ChannelDispatcherBase,
virtual void SetCapabilities(const Capabilities& capabilities) OVERRIDE;
virtual void SetPairingResponse(
const PairingResponse& pairing_response) OVERRIDE;
virtual void DeliverHostMessage(
const ExtensionMessage& message) OVERRIDE;
// ClipboardStub implementation for sending clipboard data to client.
virtual void InjectClipboardEvent(const ClipboardEvent& event) OVERRIDE;

@@ -17,6 +17,7 @@ namespace protocol {
class AudioControl;
class Capabilities;
class ClientResolution;
class ExtensionMessage;
class PairingResponse;
class PairingRequest;
class VideoControl;
@@ -43,6 +44,9 @@ class HostStub {
// Requests pairing between the host and client for PIN-less authentication.
virtual void RequestPairing(const PairingRequest& pairing_request) = 0;
// Deliver an extension message from the client to the host.
virtual void DeliverClientMessage(const ExtensionMessage& message) = 0;
protected:
virtual ~HostStub() {}

@@ -114,6 +114,7 @@ class MockHostStub : public HostStub {
MOCK_METHOD1(SetCapabilities, void(const Capabilities& capabilities));
MOCK_METHOD1(RequestPairing,
void(const PairingRequest& pairing_request));
MOCK_METHOD1(DeliverClientMessage, void(const ExtensionMessage& message));
private:
DISALLOW_COPY_AND_ASSIGN(MockHostStub);
@@ -128,6 +129,7 @@ class MockClientStub : public ClientStub {
MOCK_METHOD1(SetCapabilities, void(const Capabilities& capabilities));
MOCK_METHOD1(SetPairingResponse,
void(const PairingResponse& pairing_response));
MOCK_METHOD1(DeliverHostMessage, void(const ExtensionMessage& message));
// ClipboardStub mock implementation.
MOCK_METHOD1(InjectClipboardEvent, void(const ClipboardEvent& event));

@@ -67,7 +67,8 @@ remoting.ClientPlugin.Feature = {
SEND_CLIPBOARD_ITEM: 'sendClipboardItem',
THIRD_PARTY_AUTH: 'thirdPartyAuth',
TRAP_KEY: 'trapKey',
PINLESS_AUTH: 'pinlessAuth'
PINLESS_AUTH: 'pinlessAuth',
EXTENSION_MESSAGE: 'extensionMessage'
};
/**

@@ -313,6 +313,10 @@ remoting.ClientPluginAsync.prototype.handleMessage_ = function(messageStr) {
return;
}
this.onPairingComplete_(clientId, sharedSecret);
} else if (message.method == 'extensionMessage') {
// No messages currently supported.
console.log('Unexpected message received: ' +
message.data.type + ': ' + message.data.data);
}
};
@@ -606,6 +610,23 @@ remoting.ClientPluginAsync.prototype.requestPairing =
{ method: 'requestPairing', data: { clientName: clientName } }));
};
/**
* Send an extension message to the host.
*
* @param {string} type The message type.
* @param {Object} message The message payload.
*/
remoting.ClientPluginAsync.prototype.sendClientMessage =
function(type, message) {
if (!this.hasFeature(remoting.ClientPlugin.Feature.EXTENSION_MESSAGE)) {
return;
}
this.plugin.postMessage(JSON.stringify(
{ method: 'extensionMessage',
data: { type: type, data: JSON.stringify(message) } }));
};
/**
* If we haven't yet received a "hello" message from the plugin, change its
* size so that the user can confirm it if click-to-play is enabled, or can