summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-17 18:50:52 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-17 18:50:52 +0000
commitefd7cc50c34a77e0168f2233784912f68f60aaeb (patch)
tree69a03f2d4d9f48486b05d1d8b1b5594e8f07a64e
parent450f839ae7c238932230f624cbdf9468a5cb78e5 (diff)
downloadchromium_src-efd7cc50c34a77e0168f2233784912f68f60aaeb.zip
chromium_src-efd7cc50c34a77e0168f2233784912f68f60aaeb.tar.gz
chromium_src-efd7cc50c34a77e0168f2233784912f68f60aaeb.tar.bz2
Implement support for messaging interface in the client plugin.
This adds support for messaging interface in the plugin. The old interface (based on ScriptableObject) is still supported. BUG=88353 Review URL: https://chromiumcodereview.appspot.com/9365067 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@122540 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/client/plugin/chromoting_instance.cc336
-rw-r--r--remoting/client/plugin/chromoting_instance.h86
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.cc162
-rw-r--r--remoting/client/plugin/chromoting_scriptable_object.h43
-rw-r--r--remoting/client/plugin/pepper_view.cc35
-rw-r--r--remoting/client/plugin/pepper_xmpp_proxy.cc10
-rw-r--r--remoting/client/plugin/pepper_xmpp_proxy.h11
7 files changed, 447 insertions, 236 deletions
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc
index d961e1b..1b0b52b 100644
--- a/remoting/client/plugin/chromoting_instance.cc
+++ b/remoting/client/plugin/chromoting_instance.cc
@@ -8,10 +8,14 @@
#include <vector>
#include "base/bind.h"
+#include "base/callback.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/stringprintf.h"
+#include "base/string_split.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
@@ -35,8 +39,53 @@
#include "remoting/protocol/host_stub.h"
#include "remoting/protocol/key_event_tracker.h"
+// Windows defines 'PostMessage', so we have to undef it.
+#if defined(PostMessage)
+#undef PostMessage
+#endif
+
namespace remoting {
+namespace {
+
+const int kPerfStatsIntervalMs = 1000;
+
+std::string ConnectionStateToString(ChromotingInstance::ConnectionState state) {
+ switch (state) {
+ case ChromotingInstance::STATE_CONNECTING:
+ return "CONNECTING";
+ case ChromotingInstance::STATE_INITIALIZING:
+ return "INITIALIZING";
+ case ChromotingInstance::STATE_CONNECTED:
+ return "CONNECTED";
+ case ChromotingInstance::STATE_CLOSED:
+ return "CLOSED";
+ case ChromotingInstance::STATE_FAILED:
+ return "FAILED";
+ }
+ NOTREACHED();
+ return "";
+}
+
+std::string ConnectionErrorToString(ChromotingInstance::ConnectionError error) {
+ switch (error) {
+ case ChromotingInstance::ERROR_NONE:
+ return "NONE";
+ case ChromotingInstance::ERROR_HOST_IS_OFFLINE:
+ return "HOST_IS_OFFLINE";
+ case ChromotingInstance::ERROR_SESSION_REJECTED:
+ return "SESSION_REJECTED";
+ case ChromotingInstance::ERROR_INCOMPATIBLE_PROTOCOL:
+ return "INCOMPATIBLE_PROTOCOL";
+ case ChromotingInstance::ERROR_NETWORK_FAILURE:
+ return "NETWORK_FAILURE";
+ }
+ NOTREACHED();
+ return "";
+}
+
+} // namespace
+
// This flag blocks LOGs to the UI if we're already in the middle of logging
// to the UI. This prevents a potential infinite loop if we encounter an error
// while sending the log message to the UI.
@@ -48,19 +97,49 @@ static logging::LogMessageHandlerFunction g_logging_old_handler = NULL;
static base::LazyInstance<base::Lock>::Leaky
g_logging_lock = LAZY_INSTANCE_INITIALIZER;
+bool ChromotingInstance::ParseAuthMethods(const std::string& auth_methods_str,
+ ClientConfig* config) {
+ if (auth_methods_str == "v1_token") {
+ config->use_v1_authenticator = true;
+ } else {
+ config->use_v1_authenticator = false;
+
+ std::vector<std::string> auth_methods;
+ base::SplitString(auth_methods_str, ',', &auth_methods);
+ for (std::vector<std::string>::iterator it = auth_methods.begin();
+ it != auth_methods.end(); ++it) {
+ protocol::AuthenticationMethod authentication_method =
+ protocol::AuthenticationMethod::FromString(*it);
+ if (authentication_method.is_valid())
+ config->authentication_methods.push_back(authentication_method);
+ }
+ if (config->authentication_methods.empty()) {
+ LOG(ERROR) << "No valid authentication methods specified.";
+ return false;
+ }
+ }
+
+ return true;
+}
+
ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
: pp::InstancePrivate(pp_instance),
initialized_(false),
plugin_message_loop_(
new PluginMessageLoopProxy(&plugin_thread_delegate_)),
context_(plugin_message_loop_),
- scale_to_fit_(false),
thread_proxy_(new ScopedThreadProxy(plugin_message_loop_)) {
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL);
RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
// Resister this instance to handle debug log messsages.
RegisterLoggingInstance();
+
+ // Send hello message.
+ scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
+ data->SetInteger("apiVersion", kApiVersion);
+ data->SetInteger("apiMinVersion", kApiMinMessagingVersion);
+ PostChromotingMessage("hello", data.Pass());
}
ChromotingInstance::~ChromotingInstance() {
@@ -129,6 +208,129 @@ bool ChromotingInstance::Init(uint32_t argc,
return true;
}
+void ChromotingInstance::HandleMessage(const pp::Var& message) {
+ if (!message.is_string()) {
+ LOG(ERROR) << "Received a message that is not a string.";
+ return;
+ }
+
+ scoped_ptr<base::Value> json(
+ base::JSONReader::Read(message.AsString(), true));
+ base::DictionaryValue* message_dict = NULL;
+ std::string method;
+ base::DictionaryValue* data = NULL;
+ if (!json.get() ||
+ !json->GetAsDictionary(&message_dict) ||
+ !message_dict->GetString("method", &method) ||
+ !message_dict->GetDictionary("data", &data)) {
+ LOG(ERROR) << "Received invalid message:" << message.AsString();
+ return;
+ }
+
+ if (method == "connect") {
+ ClientConfig config;
+ std::string auth_methods;
+ if (!data->GetString("hostJid", &config.host_jid) ||
+ !data->GetString("hostPublicKey", &config.host_public_key) ||
+ !data->GetString("localJid", &config.local_jid) ||
+ !data->GetString("sharedSecret", &config.shared_secret) ||
+ !data->GetString("authenticationMethods", &auth_methods) ||
+ !ParseAuthMethods(auth_methods, &config) ||
+ !data->GetString("authenticationTag", &config.authentication_tag)) {
+ LOG(ERROR) << "Invalid connect() data.";
+ return;
+ }
+
+ Connect(config);
+ } else if (method == "disconnect") {
+ Disconnect();
+ } else if (method == "incomingIq") {
+ std::string iq;
+ if (!data->GetString("iq", &iq)) {
+ LOG(ERROR) << "Invalid onIq() data.";
+ return;
+ }
+ OnIncomingIq(iq);
+ } else if (method == "releaseAllKeys") {
+ ReleaseAllKeys();
+ }
+}
+
+void ChromotingInstance::DidChangeView(const pp::Rect& position,
+ const pp::Rect& clip) {
+ DCHECK(plugin_message_loop_->BelongsToCurrentThread());
+
+ SkISize new_size = SkISize::Make(position.width(), position.height());
+ if (view_->SetViewSize(new_size)) {
+ if (mouse_input_filter_.get()) {
+ mouse_input_filter_->set_input_size(new_size);
+ }
+ rectangle_decoder_->SetOutputSize(new_size);
+ }
+
+ rectangle_decoder_->UpdateClipRect(
+ SkIRect::MakeXYWH(clip.x(), clip.y(), clip.width(), clip.height()));
+}
+
+bool ChromotingInstance::HandleInputEvent(const pp::InputEvent& event) {
+ DCHECK(plugin_message_loop_->BelongsToCurrentThread());
+
+ if (!input_handler_.get())
+ return false;
+
+ // TODO(wez): When we have a good hook into Host dimensions changes, move
+ // this there.
+ // If |input_handler_| is valid, then |mouse_input_filter_| must also be
+ // since they are constructed together as part of the input pipeline
+ mouse_input_filter_->set_output_size(view_->get_host_size());
+
+ return input_handler_->HandleInputEvent(event);
+}
+
+pp::Var ChromotingInstance::GetInstanceObject() {
+ if (instance_object_.is_undefined()) {
+ ChromotingScriptableObject* object =
+ new ChromotingScriptableObject(this, plugin_message_loop_);
+ object->Init();
+
+ // The pp::Var takes ownership of object here.
+ instance_object_ = pp::VarPrivate(this, object);
+ }
+
+ return instance_object_;
+}
+
+void ChromotingInstance::SetDesktopSize(int width, int height) {
+ scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
+ data->SetInteger("width", width);
+ data->SetInteger("height", height);
+ PostChromotingMessage("onDesktopSize", data.Pass());
+
+ GetScriptableObject()->SetDesktopSize(width, height);
+}
+
+void ChromotingInstance::SetConnectionState(
+ ConnectionState state,
+ ConnectionError error) {
+ scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
+ data->SetString("state", ConnectionStateToString(state));
+ data->SetString("error", ConnectionErrorToString(error));
+ PostChromotingMessage("onConnectionStatus", data.Pass());
+
+ GetScriptableObject()->SetConnectionStatus(state, error);
+}
+
+ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() {
+ pp::VarPrivate object = GetInstanceObject();
+ if (!object.is_undefined()) {
+ pp::deprecated::ScriptableObject* so = object.AsScriptableObject();
+ DCHECK(so != NULL);
+ return static_cast<ChromotingScriptableObject*>(so);
+ }
+ LOG(ERROR) << "Unable to get ScriptableObject for Chromoting plugin.";
+ return NULL;
+}
+
void ChromotingInstance::Connect(const ClientConfig& config) {
DCHECK(plugin_message_loop_->BelongsToCurrentThread());
@@ -151,20 +353,21 @@ void ChromotingInstance::Connect(const ClientConfig& config) {
<< ". Local jid: " << config.local_jid << ".";
// Setup the XMPP Proxy.
- ChromotingScriptableObject* scriptable_object = GetScriptableObject();
- scoped_refptr<PepperXmppProxy> xmpp_proxy =
- new PepperXmppProxy(scriptable_object->AsWeakPtr(),
- plugin_message_loop_,
- context_.network_message_loop());
- scriptable_object->AttachXmppProxy(xmpp_proxy);
+ xmpp_proxy_ = new PepperXmppProxy(
+ base::Bind(&ChromotingInstance::SendOutgoingIq, AsWeakPtr()),
+ plugin_message_loop_,
+ context_.network_message_loop());
// Kick off the connection.
- client_->Start(xmpp_proxy);
+ client_->Start(xmpp_proxy_);
+
+ // Start timer that periodically sends perf stats.
+ plugin_message_loop_->PostDelayedTask(
+ FROM_HERE, base::Bind(&ChromotingInstance::SendPerfStats, AsWeakPtr()),
+ kPerfStatsIntervalMs);
VLOG(1) << "Connection status: Initializing";
- GetScriptableObject()->SetConnectionStatus(
- ChromotingScriptableObject::STATUS_INITIALIZING,
- ChromotingScriptableObject::ERROR_NONE);
+ SetConnectionState(STATE_INITIALIZING, ERROR_NONE);
}
void ChromotingInstance::Disconnect() {
@@ -185,51 +388,64 @@ void ChromotingInstance::Disconnect() {
mouse_input_filter_.reset();
host_connection_.reset();
- GetScriptableObject()->SetConnectionStatus(
- ChromotingScriptableObject::STATUS_CLOSED,
- ChromotingScriptableObject::ERROR_NONE);
+ SetConnectionState(STATE_CLOSED, ERROR_NONE);
}
-void ChromotingInstance::DidChangeView(const pp::Rect& position,
- const pp::Rect& clip) {
- DCHECK(plugin_message_loop_->BelongsToCurrentThread());
+void ChromotingInstance::OnIncomingIq(const std::string& iq) {
+ xmpp_proxy_->OnIq(iq);
+}
- SkISize new_size = SkISize::Make(position.width(), position.height());
- if (view_->SetViewSize(new_size)) {
- if (mouse_input_filter_.get()) {
- mouse_input_filter_->set_input_size(new_size);
- }
- rectangle_decoder_->SetOutputSize(new_size);
+void ChromotingInstance::ReleaseAllKeys() {
+ if (key_event_tracker_.get()) {
+ key_event_tracker_->ReleaseAllKeys();
}
+}
- rectangle_decoder_->UpdateClipRect(
- SkIRect::MakeXYWH(clip.x(), clip.y(), clip.width(), clip.height()));
+ChromotingStats* ChromotingInstance::GetStats() {
+ if (!client_.get())
+ return NULL;
+ return client_->GetStats();
}
-bool ChromotingInstance::HandleInputEvent(const pp::InputEvent& event) {
- DCHECK(plugin_message_loop_->BelongsToCurrentThread());
+void ChromotingInstance::PostChromotingMessage(
+ const std::string& method,
+ scoped_ptr<base::DictionaryValue> data) {
+ scoped_ptr<base::DictionaryValue> message(new base::DictionaryValue());
+ message->SetString("method", method);
+ message->Set("data", data.release());
- if (!input_handler_.get())
- return false;
+ std::string message_json;
+ base::JSONWriter::Write(message.get(), false, &message_json);
+ PostMessage(pp::Var(message_json));
+}
- // TODO(wez): When we have a good hook into Host dimensions changes, move
- // this there.
- // If |input_handler_| is valid, then |mouse_input_filter_| must also be
- // since they are constructed together as part of the input pipeline
- mouse_input_filter_->set_output_size(view_->get_host_size());
+void ChromotingInstance::SendOutgoingIq(const std::string& iq) {
+ scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
+ data->SetString("iq", iq);
+ PostChromotingMessage("sendOutgoingIq", data.Pass());
- return input_handler_->HandleInputEvent(event);
+ GetScriptableObject()->SendIq(iq);
}
-ChromotingScriptableObject* ChromotingInstance::GetScriptableObject() {
- pp::VarPrivate object = GetInstanceObject();
- if (!object.is_undefined()) {
- pp::deprecated::ScriptableObject* so = object.AsScriptableObject();
- DCHECK(so != NULL);
- return static_cast<ChromotingScriptableObject*>(so);
+void ChromotingInstance::SendPerfStats() {
+ if (!client_.get()) {
+ return;
}
- LOG(ERROR) << "Unable to get ScriptableObject for Chromoting plugin.";
- return NULL;
+
+ plugin_message_loop_->PostDelayedTask(
+ FROM_HERE, base::Bind(&ChromotingInstance::SendPerfStats, AsWeakPtr()),
+ kPerfStatsIntervalMs);
+
+ scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
+ ChromotingStats* stats = client_->GetStats();
+ data->SetDouble("videoBandwidth", stats->video_bandwidth()->Rate());
+ data->SetDouble("videoFrameRate", stats->video_frame_rate()->Rate());
+ data->SetDouble("captureLatency", stats->video_capture_ms()->Average());
+ data->SetDouble("encodeLatency", stats->video_encode_ms()->Average());
+ data->SetDouble("decodeLatency", stats->video_decode_ms()->Average());
+ data->SetDouble("renderLatency", stats->video_paint_ms()->Average());
+ data->SetDouble("roundtripLatency", stats->round_trip_ms()->Average());
+ PostChromotingMessage("onPerfStats", data.Pass());
}
// static
@@ -321,35 +537,15 @@ void ChromotingInstance::ProcessLogToUI(const std::string& message) {
// new tasks while we're in the middle of servicing a LOG call. This can
// happen if the call to LogDebugInfo tries to LOG anything.
g_logging_to_plugin = true;
- ChromotingScriptableObject* cso = GetScriptableObject();
- if (cso)
- cso->LogDebugInfo(message);
- g_logging_to_plugin = false;
-}
-
-pp::Var ChromotingInstance::GetInstanceObject() {
- if (instance_object_.is_undefined()) {
- ChromotingScriptableObject* object =
- new ChromotingScriptableObject(this, plugin_message_loop_);
- object->Init();
-
- // The pp::Var takes ownership of object here.
- instance_object_ = pp::VarPrivate(this, object);
- }
-
- return instance_object_;
-}
-
-ChromotingStats* ChromotingInstance::GetStats() {
- if (!client_.get())
- return NULL;
- return client_->GetStats();
-}
+ ChromotingScriptableObject* scriptable_object = GetScriptableObject();
+ if (scriptable_object) {
+ scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
+ data->SetString("message", message);
+ PostChromotingMessage("logDebugMessage", data.Pass());
-void ChromotingInstance::ReleaseAllKeys() {
- if (key_event_tracker_.get()) {
- key_event_tracker_->ReleaseAllKeys();
+ scriptable_object->LogDebugInfo(message);
}
+ g_logging_to_plugin = false;
}
} // namespace remoting
diff --git a/remoting/client/plugin/chromoting_instance.h b/remoting/client/plugin/chromoting_instance.h
index 5c72bf1..734c574 100644
--- a/remoting/client/plugin/chromoting_instance.h
+++ b/remoting/client/plugin/chromoting_instance.h
@@ -12,17 +12,28 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/cpp/var.h"
+
+// Windows defines 'PostMessage', so we have to undef it before we
+// include instance_private.h
+#if defined(PostMessage)
+#undef PostMessage
+#endif
+
#include "ppapi/cpp/private/instance_private.h"
#include "remoting/base/scoped_thread_proxy.h"
#include "remoting/client/client_context.h"
-#include "remoting/client/plugin/chromoting_scriptable_object.h"
#include "remoting/client/plugin/pepper_plugin_thread_delegate.h"
#include "remoting/protocol/connection_to_host.h"
+namespace base {
+class DictionaryBase;
+} // namespace base
+
namespace pp {
class InputEvent;
class Module;
@@ -36,18 +47,60 @@ class KeyEventTracker;
} // namespace protocol
class ChromotingClient;
+class ChromotingScriptableObject;
class ChromotingStats;
class ClientContext;
class FrameConsumerProxy;
class MouseInputFilter;
class PepperInputHandler;
class PepperView;
+class PepperXmppProxy;
class RectangleUpdateDecoder;
struct ClientConfig;
-class ChromotingInstance : public pp::InstancePrivate {
+class ChromotingInstance :
+ public pp::InstancePrivate,
+ public base::SupportsWeakPtr<ChromotingInstance> {
public:
+ // These state values are duplicated in the JS code. Remember to
+ // update both copies when making changes.
+ enum ConnectionState {
+ STATE_CONNECTING = 1,
+ STATE_INITIALIZING,
+ STATE_CONNECTED,
+ STATE_CLOSED,
+ STATE_FAILED,
+ };
+
+ // These values are duplicated in the JS code. Remember to update
+ // both copies when making changes.
+ enum ConnectionError {
+ ERROR_NONE = 0,
+ ERROR_HOST_IS_OFFLINE,
+ ERROR_SESSION_REJECTED,
+ ERROR_INCOMPATIBLE_PROTOCOL,
+ ERROR_NETWORK_FAILURE,
+ };
+
+ // Plugin API version. This should be incremented whenever the API
+ // interface changes.
+ static const int kApiVersion = 5;
+
+ // Backward-compatibility version used by for the messaging
+ // interface. Should be updated whenever we remove support for
+ // an older version of the API.
+ static const int kApiMinMessagingVersion = 5;
+
+ // Backward-compatibility version used by for the ScriptableObject
+ // interface. Should be updated whenever we remove support for
+ // an older version of the API.
+ static const int kApiMinScriptableVersion = 2;
+
+ // Helper method to parse authentication_methods parameter.
+ static bool ParseAuthMethods(const std::string& auth_methods,
+ ClientConfig* config);
+
explicit ChromotingInstance(PP_Instance instance);
virtual ~ChromotingInstance();
@@ -56,29 +109,30 @@ class ChromotingInstance : public pp::InstancePrivate {
const pp::Rect& clip) OVERRIDE;
virtual bool Init(uint32_t argc, const char* argn[],
const char* argv[]) OVERRIDE;
+ virtual void HandleMessage(const pp::Var& message) OVERRIDE;
virtual bool HandleInputEvent(const pp::InputEvent& event) OVERRIDE;
// pp::InstancePrivate interface.
virtual pp::Var GetInstanceObject() OVERRIDE;
+ // Called by PepperView.
+ void SetDesktopSize(int width, int height);
+ void SetConnectionState(ConnectionState state, ConnectionError error);
+
// Convenience wrapper to get the ChromotingScriptableObject.
ChromotingScriptableObject* GetScriptableObject();
- // Initiates and cancels connections.
+ // Message handlers for messages that come from JavaScript. Called
+ // from HandleMessage() and ChromotingScriptableObject.
void Connect(const ClientConfig& config);
void Disconnect();
-
- // Called by ChromotingScriptableObject to set scale-to-fit.
- void SetScaleToFit(bool scale_to_fit);
+ void OnIncomingIq(const std::string& iq);
+ void ReleaseAllKeys();
// Return statistics record by ChromotingClient.
// If no connection is currently active then NULL will be returned.
ChromotingStats* GetStats();
- void ReleaseAllKeys();
-
- bool DoScaling() const { return scale_to_fit_; }
-
// Registers a global log message handler that redirects the log output to
// our plugin instance.
// This is called by the plugin's PPP_InitializeModule.
@@ -104,6 +158,15 @@ class ChromotingInstance : public pp::InstancePrivate {
private:
FRIEND_TEST_ALL_PREFIXES(ChromotingInstanceTest, TestCaseSetup);
+ // Helper method to post messages to the webapp.
+ void PostChromotingMessage(const std::string& method,
+ scoped_ptr<base::DictionaryValue> data);
+
+ // Callback for PepperXmppProxy.
+ void SendOutgoingIq(const std::string& iq);
+
+ void SendPerfStats();
+
void ProcessLogToUI(const std::string& message);
bool initialized_;
@@ -114,9 +177,6 @@ class ChromotingInstance : public pp::InstancePrivate {
scoped_ptr<protocol::ConnectionToHost> host_connection_;
scoped_ptr<PepperView> view_;
- // True if scale to fit is enabled.
- bool scale_to_fit_;
-
scoped_refptr<FrameConsumerProxy> consumer_proxy_;
scoped_refptr<RectangleUpdateDecoder> rectangle_decoder_;
scoped_ptr<MouseInputFilter> mouse_input_filter_;
diff --git a/remoting/client/plugin/chromoting_scriptable_object.cc b/remoting/client/plugin/chromoting_scriptable_object.cc
index 9028bf7..a6dbf0e 100644
--- a/remoting/client/plugin/chromoting_scriptable_object.cc
+++ b/remoting/client/plugin/chromoting_scriptable_object.cc
@@ -5,10 +5,10 @@
#include "remoting/client/plugin/chromoting_scriptable_object.h"
#include "base/bind.h"
+#include "base/callback.h"
#include "base/logging.h"
#include "base/message_loop_proxy.h"
#include "base/string_split.h"
-// TODO(wez): Remove this when crbug.com/86353 is complete.
#include "ppapi/cpp/private/var_private.h"
#include "remoting/base/auth_token_util.h"
#include "remoting/client/client_config.h"
@@ -56,34 +56,38 @@ void ChromotingScriptableObject::Init() {
// Property addition order should match the interface description at the
// top of chromoting_scriptable_object.h.
- // Plugin API version.
- // This should be incremented whenever the API interface changes.
- AddAttribute(kApiVersionAttribute, Var(4));
+ AddAttribute(kApiVersionAttribute, Var(ChromotingInstance::kApiVersion));
- // This should be updated whenever we remove support for an older version
- // of the API.
- AddAttribute(kApiMinVersionAttribute, Var(2));
+ AddAttribute(kApiMinVersionAttribute,
+ Var(ChromotingInstance::kApiMinScriptableVersion));
// Connection status.
- AddAttribute(kStatusAttribute, Var(STATUS_UNKNOWN));
+ AddAttribute(kStatusAttribute, Var(0)); // STATUS_UNKNOWN
// Connection status values.
- AddAttribute("STATUS_UNKNOWN", Var(STATUS_UNKNOWN));
- AddAttribute("STATUS_CONNECTING", Var(STATUS_CONNECTING));
- AddAttribute("STATUS_INITIALIZING", Var(STATUS_INITIALIZING));
- AddAttribute("STATUS_CONNECTED", Var(STATUS_CONNECTED));
- AddAttribute("STATUS_CLOSED", Var(STATUS_CLOSED));
- AddAttribute("STATUS_FAILED", Var(STATUS_FAILED));
+ // TODO(jamiewalch): Remove STATUS_UNKNOWN once all web-apps that might try
+ // to access it have been upgraded.
+ AddAttribute("STATUS_UNKNOWN", Var(0));
+ AddAttribute("STATUS_CONNECTING", Var(ChromotingInstance::STATE_CONNECTING));
+ AddAttribute("STATUS_INITIALIZING",
+ Var(ChromotingInstance::STATE_INITIALIZING));
+ AddAttribute("STATUS_CONNECTED", Var(ChromotingInstance::STATE_CONNECTED));
+ AddAttribute("STATUS_CLOSED", Var(ChromotingInstance::STATE_CLOSED));
+ AddAttribute("STATUS_FAILED", Var(ChromotingInstance::STATE_FAILED));
// Connection error.
- AddAttribute(kErrorAttribute, Var(ERROR_NONE));
-
- // Connection status values.
- AddAttribute("ERROR_NONE", Var(ERROR_NONE));
- AddAttribute("ERROR_HOST_IS_OFFLINE", Var(ERROR_HOST_IS_OFFLINE));
- AddAttribute("ERROR_SESSION_REJECTED", Var(ERROR_SESSION_REJECTED));
- AddAttribute("ERROR_INCOMPATIBLE_PROTOCOL", Var(ERROR_INCOMPATIBLE_PROTOCOL));
- AddAttribute("ERROR_FAILURE_NONE", Var(ERROR_NETWORK_FAILURE));
+ AddAttribute(kErrorAttribute, Var(ChromotingInstance::ERROR_NONE));
+
+ // Connection error values.
+ AddAttribute("ERROR_NONE", Var(ChromotingInstance::ERROR_NONE));
+ AddAttribute("ERROR_HOST_IS_OFFLINE",
+ Var(ChromotingInstance::ERROR_HOST_IS_OFFLINE));
+ AddAttribute("ERROR_SESSION_REJECTED",
+ Var(ChromotingInstance::ERROR_SESSION_REJECTED));
+ AddAttribute("ERROR_INCOMPATIBLE_PROTOCOL",
+ Var(ChromotingInstance::ERROR_INCOMPATIBLE_PROTOCOL));
+ AddAttribute("ERROR_FAILURE_NONE",
+ Var(ChromotingInstance::ERROR_NETWORK_FAILURE));
// Debug info to display.
AddAttribute(kConnectionInfoUpdate, Var());
@@ -231,14 +235,15 @@ Var ChromotingScriptableObject::Call(const Var& method_name,
}
void ChromotingScriptableObject::SetConnectionStatus(
- ConnectionStatus status, ConnectionError error) {
- VLOG(1) << "Connection status is updated: " << status;
+ ChromotingInstance::ConnectionState state,
+ ChromotingInstance::ConnectionError error) {
+ VLOG(1) << "Connection status is updated: " << state;
bool signal = false;
int status_index = property_names_[kStatusAttribute];
- if (properties_[status_index].attribute.AsInt() != status) {
- properties_[status_index].attribute = Var(status);
+ if (properties_[status_index].attribute.AsInt() != state) {
+ properties_[status_index].attribute = Var(state);
signal = true;
}
@@ -248,21 +253,27 @@ void ChromotingScriptableObject::SetConnectionStatus(
signal = true;
}
- if (signal)
- SignalConnectionInfoChange(status, error);
+ if (signal) {
+ plugin_message_loop_->PostTask(
+ FROM_HERE, base::Bind(
+ &ChromotingScriptableObject::DoSignalConnectionInfoChange,
+ AsWeakPtr(), state, error));
+ }
}
void ChromotingScriptableObject::LogDebugInfo(const std::string& info) {
Var exception;
VarPrivate cb = GetProperty(Var(kDebugInfo), &exception);
- // Var() means call the object directly as a function rather than calling
- // a method in the object.
- cb.Call(Var(), Var(info), &exception);
+ if (!cb.is_undefined()) {
+ // Var() means call the object directly as a function rather than calling
+ // a method in the object.
+ cb.Call(Var(), Var(info), &exception);
- if (!exception.is_undefined()) {
- LOG(WARNING) << "Exception when invoking debugInfo JS callback: "
- << exception.DebugString();
+ if (!exception.is_undefined()) {
+ LOG(WARNING) << "Exception when invoking debugInfo JS callback: "
+ << exception.DebugString();
+ }
}
}
@@ -274,16 +285,15 @@ void ChromotingScriptableObject::SetDesktopSize(int width, int height) {
properties_[height_index].attribute.AsInt() != height) {
properties_[width_index].attribute = Var(width);
properties_[height_index].attribute = Var(height);
- SignalDesktopSizeChange();
+ plugin_message_loop_->PostTask(
+ FROM_HERE, base::Bind(
+ &ChromotingScriptableObject::DoSignalDesktopSizeChange,
+ AsWeakPtr()));
}
VLOG(1) << "Update desktop size to: " << width << " x " << height;
}
-void ChromotingScriptableObject::AttachXmppProxy(PepperXmppProxy* xmpp_proxy) {
- xmpp_proxy_ = xmpp_proxy;
-}
-
void ChromotingScriptableObject::SendIq(const std::string& message_xml) {
plugin_message_loop_->PostTask(
FROM_HERE, base::Bind(
@@ -302,43 +312,32 @@ void ChromotingScriptableObject::AddMethod(const std::string& name,
properties_.push_back(PropertyDescriptor(name, handler));
}
-void ChromotingScriptableObject::SignalConnectionInfoChange(int status,
- int error) {
- plugin_message_loop_->PostTask(
- FROM_HERE, base::Bind(
- &ChromotingScriptableObject::DoSignalConnectionInfoChange,
- AsWeakPtr(), status, error));
-}
-
-void ChromotingScriptableObject::SignalDesktopSizeChange() {
- plugin_message_loop_->PostTask(
- FROM_HERE, base::Bind(
- &ChromotingScriptableObject::DoSignalDesktopSizeChange,
- AsWeakPtr()));
-}
-
-void ChromotingScriptableObject::DoSignalConnectionInfoChange(int status,
+void ChromotingScriptableObject::DoSignalConnectionInfoChange(int state,
int error) {
Var exception;
VarPrivate cb = GetProperty(Var(kConnectionInfoUpdate), &exception);
- // |this| must not be touched after Call() returns.
- cb.Call(Var(), Var(status), Var(error), &exception);
+ if (!cb.is_undefined()) {
+ // |this| must not be touched after Call() returns.
+ cb.Call(Var(), Var(state), Var(error), &exception);
- if (!exception.is_undefined())
- LOG(ERROR) << "Exception when invoking connectionInfoUpdate JS callback.";
+ if (!exception.is_undefined())
+ LOG(ERROR) << "Exception when invoking connectionInfoUpdate JS callback.";
+ }
}
void ChromotingScriptableObject::DoSignalDesktopSizeChange() {
Var exception;
VarPrivate cb = GetProperty(Var(kDesktopSizeUpdate), &exception);
- // |this| must not be touched after Call() returns.
- cb.Call(Var(), &exception);
+ if (!cb.is_undefined()) {
+ // |this| must not be touched after Call() returns.
+ cb.Call(Var(), &exception);
- if (!exception.is_undefined()) {
- LOG(ERROR) << "Exception when invoking JS callback"
- << exception.DebugString();
+ if (!exception.is_undefined()) {
+ LOG(ERROR) << "Exception when invoking JS callback"
+ << exception.DebugString();
+ }
}
}
@@ -346,11 +345,13 @@ void ChromotingScriptableObject::DoSendIq(const std::string& message_xml) {
Var exception;
VarPrivate cb = GetProperty(Var(kSendIq), &exception);
- // |this| must not be touched after Call() returns.
- cb.Call(Var(), Var(message_xml), &exception);
+ if (!cb.is_undefined()) {
+ // |this| must not be touched after Call() returns.
+ cb.Call(Var(), Var(message_xml), &exception);
- if (!exception.is_undefined())
- LOG(ERROR) << "Exception when invoking sendiq JS callback.";
+ if (!exception.is_undefined())
+ LOG(ERROR) << "Exception when invoking sendiq JS callback.";
+ }
}
Var ChromotingScriptableObject::DoConnect(const std::vector<Var>& args,
@@ -400,25 +401,10 @@ Var ChromotingScriptableObject::DoConnect(const std::vector<Var>& args,
return Var();
}
- std::string as_string = args[arg++].AsString();
- if (as_string == "v1_token") {
- config.use_v1_authenticator = true;
- } else {
- config.use_v1_authenticator = false;
-
- std::vector<std::string> auth_methods;
- base::SplitString(as_string, ',', &auth_methods);
- for (std::vector<std::string>::iterator it = auth_methods.begin();
- it != auth_methods.end(); ++it) {
- protocol::AuthenticationMethod authentication_method =
- protocol::AuthenticationMethod::FromString(*it);
- if (authentication_method.is_valid())
- config.authentication_methods.push_back(authentication_method);
- }
- if (config.authentication_methods.empty()) {
- *exception = Var("No valid authentication methods specified.");
- return Var();
- }
+ if (!ChromotingInstance::ParseAuthMethods(
+ args[arg++].AsString(), &config)) {
+ *exception = Var("No valid authentication methods specified.");
+ return Var();
}
}
@@ -467,7 +453,7 @@ Var ChromotingScriptableObject::DoOnIq(const std::vector<Var>& args,
return Var();
}
- xmpp_proxy_->OnIq(args[0].AsString());
+ instance_->OnIncomingIq(args[0].AsString());
return Var();
}
diff --git a/remoting/client/plugin/chromoting_scriptable_object.h b/remoting/client/plugin/chromoting_scriptable_object.h
index 8e50797..f040ee5 100644
--- a/remoting/client/plugin/chromoting_scriptable_object.h
+++ b/remoting/client/plugin/chromoting_scriptable_object.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -105,6 +105,7 @@
#include "base/memory/weak_ptr.h"
#include "ppapi/cpp/dev/scriptable_object_deprecated.h"
#include "ppapi/cpp/var.h"
+#include "remoting/client/plugin/chromoting_instance.h"
namespace base {
class MessageLoopProxy;
@@ -112,36 +113,12 @@ class MessageLoopProxy;
namespace remoting {
-class ChromotingInstance;
-class PepperXmppProxy;
-
+// TODO(sergeyu): Remove this class when migration to messaging
+// interface is finished (crbug.com/86353).
class ChromotingScriptableObject
: public pp::deprecated::ScriptableObject,
public base::SupportsWeakPtr<ChromotingScriptableObject> {
public:
- // These state values are duplicated in the JS code. Remember to update both
- // copies when making changes.
- enum ConnectionStatus {
- // TODO(jamiewalch): Remove STATUS_UNKNOWN once all web-apps that might try
- // to access it have been upgraded.
- STATUS_UNKNOWN = 0,
- STATUS_CONNECTING,
- STATUS_INITIALIZING,
- STATUS_CONNECTED,
- STATUS_CLOSED,
- STATUS_FAILED,
- };
-
- // These state values are duplicated in the JS code. Remember to update both
- // copies when making changes.
- enum ConnectionError {
- ERROR_NONE = 0,
- ERROR_HOST_IS_OFFLINE,
- ERROR_SESSION_REJECTED,
- ERROR_INCOMPATIBLE_PROTOCOL,
- ERROR_NETWORK_FAILURE,
- };
-
ChromotingScriptableObject(
ChromotingInstance* instance,
base::MessageLoopProxy* plugin_message_loop);
@@ -162,14 +139,11 @@ class ChromotingScriptableObject
const std::vector<pp::Var>& args,
pp::Var* exception) OVERRIDE;
- void SetConnectionStatus(ConnectionStatus status, ConnectionError error);
+ void SetConnectionStatus(ChromotingInstance::ConnectionState state,
+ ChromotingInstance::ConnectionError error);
void LogDebugInfo(const std::string& info);
void SetDesktopSize(int width, int height);
- // Attaches the XmppProxy used for issuing and receivng IQ stanzas for
- // initializing a jingle connection from within the sandbox.
- void AttachXmppProxy(PepperXmppProxy* xmpp_proxy);
-
// Sends an IQ stanza, serialized as an xml string, into Javascript for
// handling.
void SendIq(const std::string& request_xml);
@@ -202,13 +176,13 @@ class ChromotingScriptableObject
void AddAttribute(const std::string& name, pp::Var attribute);
void AddMethod(const std::string& name, MethodHandler handler);
- void SignalConnectionInfoChange(int status, int error);
+ void SignalConnectionInfoChange(int state, int error);
void SignalDesktopSizeChange();
// Calls to these methods are posted to the plugin thread so that we
// call JavaScript with clean stack. This is necessary because
// JavaScript event handlers may destroy the plugin.
- void DoSignalConnectionInfoChange(int status, int error);
+ void DoSignalConnectionInfoChange(int state, int error);
void DoSignalDesktopSizeChange();
void DoSendIq(const std::string& message_xml);
@@ -229,7 +203,6 @@ class ChromotingScriptableObject
PropertyNameMap property_names_;
std::vector<PropertyDescriptor> properties_;
- scoped_refptr<PepperXmppProxy> xmpp_proxy_;
ChromotingInstance* instance_;
diff --git a/remoting/client/plugin/pepper_view.cc b/remoting/client/plugin/pepper_view.cc
index fe404c2..b466fa6 100644
--- a/remoting/client/plugin/pepper_view.cc
+++ b/remoting/client/plugin/pepper_view.cc
@@ -22,22 +22,22 @@ namespace remoting {
namespace {
-ChromotingScriptableObject::ConnectionError ConvertConnectionError(
+ChromotingInstance::ConnectionError ConvertConnectionError(
protocol::ConnectionToHost::Error error) {
switch (error) {
case protocol::ConnectionToHost::OK:
- return ChromotingScriptableObject::ERROR_NONE;
+ return ChromotingInstance::ERROR_NONE;
case protocol::ConnectionToHost::HOST_IS_OFFLINE:
- return ChromotingScriptableObject::ERROR_HOST_IS_OFFLINE;
+ return ChromotingInstance::ERROR_HOST_IS_OFFLINE;
case protocol::ConnectionToHost::SESSION_REJECTED:
- return ChromotingScriptableObject::ERROR_SESSION_REJECTED;
+ return ChromotingInstance::ERROR_SESSION_REJECTED;
case protocol::ConnectionToHost::INCOMPATIBLE_PROTOCOL:
- return ChromotingScriptableObject::ERROR_INCOMPATIBLE_PROTOCOL;
+ return ChromotingInstance::ERROR_INCOMPATIBLE_PROTOCOL;
case protocol::ConnectionToHost::NETWORK_FAILURE:
- return ChromotingScriptableObject::ERROR_NETWORK_FAILURE;
+ return ChromotingInstance::ERROR_NETWORK_FAILURE;
}
DLOG(FATAL) << "Unknown error code" << error;
- return ChromotingScriptableObject::ERROR_NONE;
+ return ChromotingInstance::ERROR_NONE;
}
} // namespace
@@ -106,8 +106,7 @@ void PepperView::SetHostSize(const SkISize& host_size) {
host_size_ = host_size;
// Submit an update of desktop size to Javascript.
- instance_->GetScriptableObject()->SetDesktopSize(
- host_size.width(), host_size.height());
+ instance_->SetDesktopSize(host_size.width(), host_size.height());
}
void PepperView::PaintFrame(media::VideoFrame* frame, const SkRegion& region) {
@@ -229,34 +228,32 @@ void PepperView::SetConnectionState(protocol::ConnectionToHost::State state,
protocol::ConnectionToHost::Error error) {
DCHECK(context_->main_message_loop()->BelongsToCurrentThread());
- // TODO(hclam): Re-consider the way we communicate with Javascript.
- ChromotingScriptableObject* scriptable_obj = instance_->GetScriptableObject();
switch (state) {
case protocol::ConnectionToHost::CONNECTING:
SetSolidFill(kCreatedColor);
- scriptable_obj->SetConnectionStatus(
- ChromotingScriptableObject::STATUS_CONNECTING,
+ instance_->SetConnectionState(
+ ChromotingInstance::STATE_CONNECTING,
ConvertConnectionError(error));
break;
case protocol::ConnectionToHost::CONNECTED:
UnsetSolidFill();
- scriptable_obj->SetConnectionStatus(
- ChromotingScriptableObject::STATUS_CONNECTED,
+ instance_->SetConnectionState(
+ ChromotingInstance::STATE_CONNECTED,
ConvertConnectionError(error));
break;
case protocol::ConnectionToHost::CLOSED:
SetSolidFill(kDisconnectedColor);
- scriptable_obj->SetConnectionStatus(
- ChromotingScriptableObject::STATUS_CLOSED,
+ instance_->SetConnectionState(
+ ChromotingInstance::STATE_CLOSED,
ConvertConnectionError(error));
break;
case protocol::ConnectionToHost::FAILED:
SetSolidFill(kFailedColor);
- scriptable_obj->SetConnectionStatus(
- ChromotingScriptableObject::STATUS_FAILED,
+ instance_->SetConnectionState(
+ ChromotingInstance::STATE_FAILED,
ConvertConnectionError(error));
break;
}
diff --git a/remoting/client/plugin/pepper_xmpp_proxy.cc b/remoting/client/plugin/pepper_xmpp_proxy.cc
index f167e6e..5ab0689 100644
--- a/remoting/client/plugin/pepper_xmpp_proxy.cc
+++ b/remoting/client/plugin/pepper_xmpp_proxy.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -7,15 +7,14 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/message_loop_proxy.h"
-#include "remoting/client/plugin/chromoting_scriptable_object.h"
namespace remoting {
PepperXmppProxy::PepperXmppProxy(
- base::WeakPtr<ChromotingScriptableObject> scriptable_object,
+ const SendIqCallback& send_iq_callback,
base::MessageLoopProxy* plugin_message_loop,
base::MessageLoopProxy* callback_message_loop)
- : scriptable_object_(scriptable_object),
+ : send_iq_callback_(send_iq_callback),
plugin_message_loop_(plugin_message_loop),
callback_message_loop_(callback_message_loop) {
DCHECK(plugin_message_loop_->BelongsToCurrentThread());
@@ -40,8 +39,7 @@ void PepperXmppProxy::SendIq(const std::string& request_xml) {
return;
}
- if (scriptable_object_)
- scriptable_object_->SendIq(request_xml);
+ send_iq_callback_.Run(request_xml);
}
void PepperXmppProxy::OnIq(const std::string& response_xml) {
diff --git a/remoting/client/plugin/pepper_xmpp_proxy.h b/remoting/client/plugin/pepper_xmpp_proxy.h
index cc3e690..40ba4ba 100644
--- a/remoting/client/plugin/pepper_xmpp_proxy.h
+++ b/remoting/client/plugin/pepper_xmpp_proxy.h
@@ -1,10 +1,11 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef REMOTING_CLIENT_PLUGIN_PEPPER_XMPP_PROXY_H_
#define REMOTING_CLIENT_PLUGIN_PEPPER_XMPP_PROXY_H_
+#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "remoting/jingle_glue/xmpp_proxy.h"
@@ -15,12 +16,12 @@ class MessageLoopProxy;
namespace remoting {
-class ChromotingScriptableObject;
-
class PepperXmppProxy : public XmppProxy {
public:
+ typedef base::Callback<void(const std::string&)> SendIqCallback;
+
PepperXmppProxy(
- base::WeakPtr<ChromotingScriptableObject> scriptable_object,
+ const SendIqCallback& send_iq_callback,
base::MessageLoopProxy* plugin_message_loop,
base::MessageLoopProxy* callback_message_loop);
@@ -43,7 +44,7 @@ class PepperXmppProxy : public XmppProxy {
private:
virtual ~PepperXmppProxy();
- base::WeakPtr<ChromotingScriptableObject> scriptable_object_;
+ SendIqCallback send_iq_callback_;
scoped_refptr<base::MessageLoopProxy> plugin_message_loop_;
scoped_refptr<base::MessageLoopProxy> callback_message_loop_;