Skip to content

Commit

Permalink
Wire up the codepath from Javascript into Jingle for IQ packets.
Browse files Browse the repository at this point in the history
Flushes out XmppProxy, the thread-safe interface that matches up Pepper with Jingle and plumbs a ConnectSandboxed method through everything so that the connection type can be chosen at runtime.

BUG=51198
TEST=Check that stanzas are sent/received from JS, and that xmpp still works.

Review URL: http://codereview.chromium.org/6603036

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@77148 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
ajwong@chromium.org committed Mar 7, 2011
1 parent a2f2e47 commit 2db5310
Show file tree
Hide file tree
Showing 22 changed files with 806 additions and 429 deletions.
21 changes: 21 additions & 0 deletions remoting/client/chromoting_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,27 @@ void ChromotingClient::Start() {
}
}

void ChromotingClient::StartSandboxed(scoped_refptr<XmppProxy> xmpp_proxy,
const std::string& your_jid,
const std::string& host_jid) {
// TODO(ajwong): Merge this with Start(), and just change behavior based on
// ClientConfig.
if (message_loop() != MessageLoop::current()) {
message_loop()->PostTask(
FROM_HERE,
NewRunnableMethod(this, &ChromotingClient::StartSandboxed, xmpp_proxy,
your_jid, host_jid));
return;
}

connection_->ConnectSandboxed(xmpp_proxy, your_jid, host_jid, this, this,
this);

if (!view_->Initialize()) {
ClientDone();
}
}

void ChromotingClient::Stop() {
if (message_loop() != MessageLoop::current()) {
message_loop()->PostTask(
Expand Down
4 changes: 4 additions & 0 deletions remoting/client/chromoting_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "remoting/protocol/connection_to_host.h"
#include "remoting/protocol/input_stub.h"
#include "remoting/protocol/video_stub.h"
#include "remoting/jingle_glue/xmpp_proxy.h"

class MessageLoop;

Expand Down Expand Up @@ -46,6 +47,9 @@ class ChromotingClient : public protocol::ConnectionToHost::HostEventCallback,
virtual ~ChromotingClient();

void Start();
void StartSandboxed(scoped_refptr<XmppProxy> xmpp_proxy,
const std::string& your_jid,
const std::string& host_jid);
void Stop();
void ClientDone();

Expand Down
55 changes: 37 additions & 18 deletions remoting/client/plugin/chromoting_instance.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include "remoting/client/plugin/pepper_input_handler.h"
#include "remoting/client/plugin/pepper_view.h"
#include "remoting/client/plugin/pepper_view_proxy.h"
#include "remoting/client/plugin/pepper_util.h"
#include "remoting/client/plugin/pepper_xmpp_proxy.h"
#include "remoting/jingle_glue/jingle_thread.h"
#include "remoting/proto/auth.pb.h"
#include "remoting/protocol/connection_to_host.h"
Expand All @@ -44,7 +46,7 @@ const char* ChromotingInstance::kMimeType = "pepper-application/x-chromoting";

ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
: pp::Instance(pp_instance),
pepper_main_loop_dont_post_to_me_(NULL) {
initialized_(false) {
}

ChromotingInstance::~ChromotingInstance() {
Expand All @@ -62,19 +64,9 @@ ChromotingInstance::~ChromotingInstance() {
bool ChromotingInstance::Init(uint32_t argc,
const char* argn[],
const char* argv[]) {
CHECK(pepper_main_loop_dont_post_to_me_ == NULL);

// Record the current thread. This function should only be invoked by the
// plugin thread, so we capture the current message loop and assume it is
// indeed the plugin thread.
//
// We're abusing the pepper API slightly here. We know we're running as an
// internal plugin, and thus we are on the pepper main thread that uses a
// message loop.
//
// TODO(ajwong): See if there is a method for querying what thread we're on
// from inside the pepper API.
pepper_main_loop_dont_post_to_me_ = MessageLoop::current();
CHECK(!initialized_);
initialized_ = true;

VLOG(1) << "Started ChromotingInstance::Init";

// Start all the threads.
Expand Down Expand Up @@ -133,6 +125,37 @@ void ChromotingInstance::Connect(const ClientConfig& config) {
QUALITY_UNKNOWN);
}

void ChromotingInstance::ConnectSandboxed(const std::string& your_jid,
const std::string& host_jid) {
// TODO(ajwong): your_jid and host_jid should be moved into ClientConfig. In
// fact, this whole function should go away, and Connect() should just look at
// ClientConfig.
DCHECK(CurrentlyOnPluginThread());

LogDebugInfo("Attempting sandboxed connection");

// Setup the XMPP Proxy.
ChromotingScriptableObject* scriptable_object = GetScriptableObject();
scoped_refptr<PepperXmppProxy> xmpp_proxy =
new PepperXmppProxy(scriptable_object->AsWeakPtr(),
context_.jingle_thread()->message_loop());
scriptable_object->AttachXmppProxy(xmpp_proxy);

client_.reset(new ChromotingClient(ClientConfig(),
&context_,
host_connection_.get(),
view_proxy_,
rectangle_decoder_.get(),
input_handler_.get(),
NULL));

// Kick off the connection.
client_->StartSandboxed(xmpp_proxy, your_jid, host_jid);

GetScriptableObject()->SetConnectionInfo(STATUS_INITIALIZING,
QUALITY_UNKNOWN);
}

void ChromotingInstance::Disconnect() {
DCHECK(CurrentlyOnPluginThread());

Expand All @@ -158,10 +181,6 @@ void ChromotingInstance::ViewChanged(const pp::Rect& position,
view_->Paint();
}

bool ChromotingInstance::CurrentlyOnPluginThread() const {
return pepper_main_loop_dont_post_to_me_ == MessageLoop::current();
}

bool ChromotingInstance::HandleInputEvent(const PP_InputEvent& event) {
DCHECK(CurrentlyOnPluginThread());

Expand Down
20 changes: 10 additions & 10 deletions remoting/client/plugin/chromoting_instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ class ChromotingInstance : public pp::Instance {

virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
virtual void Connect(const ClientConfig& config);
virtual void ConnectSandboxed(const std::string& your_jid,
const std::string& host_jid);
virtual bool HandleInputEvent(const PP_InputEvent& event);
virtual void Disconnect();
virtual pp::Var GetInstanceObject();
virtual void ViewChanged(const pp::Rect& position, const pp::Rect& clip);

virtual bool CurrentlyOnPluginThread() const;

// Convenience wrapper to get the ChromotingScriptableObject.
ChromotingScriptableObject* GetScriptableObject();

Expand All @@ -81,19 +81,13 @@ class ChromotingInstance : public pp::Instance {
private:
FRIEND_TEST_ALL_PREFIXES(ChromotingInstanceTest, TestCaseSetup);

// Since we're an internal plugin, we can just grab the message loop during
// init to figure out which thread we're on. This should only be used to
// sanity check which thread we're executing on. Do not post task here!
// Instead, use PPB_Core:CallOnMainThread() in the pepper api.
//
// TODO(ajwong): Think if there is a better way to safeguard this.
MessageLoop* pepper_main_loop_dont_post_to_me_;
bool initialized_;

ClientContext context_;
scoped_ptr<protocol::ConnectionToHost> host_connection_;
scoped_ptr<PepperView> view_;

// PepperViewProxy is refcounted and used to interface between shromoting
// PepperViewProxy is refcounted and used to interface between chromoting
// objects and PepperView and perform thread switching. It wraps around
// |view_| and receives method calls on chromoting threads. These method
// calls are then delegates on the pepper thread. During destruction of
Expand All @@ -105,6 +99,12 @@ class ChromotingInstance : public pp::Instance {
scoped_ptr<InputHandler> input_handler_;
scoped_ptr<ChromotingClient> client_;

// XmppProxy is a refcounted interface used to perform thread-switching and
// detaching between objects whose lifetimes are controlled by pepper, and
// jingle_glue objects. This is used when if we start a sandboxed jingle
// connection.
scoped_refptr<PepperXmppProxy> xmpp_proxy_;

// JavaScript interface to control this instance.
// This wraps a ChromotingScriptableObject in a pp::Var.
pp::Var instance_object_;
Expand Down
75 changes: 66 additions & 9 deletions remoting/client/plugin/chromoting_scriptable_object.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,20 @@ using pp::Var;

namespace remoting {

namespace {

const char kConnectionInfoUpdate[] = "connectionInfoUpdate";
const char kDebugInfo[] = "debugInfo";
const char kDesktopHeight[] = "desktopHeight";
const char kDesktopWidth[] = "desktopWidth";
const char kDesktopSizeUpdate[] = "desktopSizeUpdate";
const char kLoginChallenge[] = "loginChallenge";
const char kSendIq[] = "sendIq";
const char kQualityAttribute[] = "quality";
const char kStatusAttribute[] = "status";

} // namespace

ChromotingScriptableObject::ChromotingScriptableObject(
ChromotingInstance* instance)
: instance_(instance) {
Expand Down Expand Up @@ -60,12 +65,16 @@ void ChromotingScriptableObject::Init() {
AddAttribute(kDebugInfo, Var());
AddAttribute(kDesktopSizeUpdate, Var());
AddAttribute(kLoginChallenge, Var());
AddAttribute(kSendIq, Var());
AddAttribute(kDesktopWidth, Var(0));
AddAttribute(kDesktopHeight, Var(0));

AddMethod("connect", &ChromotingScriptableObject::DoConnect);
AddMethod("connectSandboxed",
&ChromotingScriptableObject::DoConnectSandboxed);
AddMethod("disconnect", &ChromotingScriptableObject::DoDisconnect);
AddMethod("submitLoginInfo", &ChromotingScriptableObject::DoSubmitLogin);
AddMethod("onIq", &ChromotingScriptableObject::DoOnIq);
}

bool ChromotingScriptableObject::HasProperty(const Var& name, Var* exception) {
Expand Down Expand Up @@ -146,6 +155,7 @@ void ChromotingScriptableObject::SetProperty(const Var& name,
property_name != kDebugInfo &&
property_name != kDesktopSizeUpdate &&
property_name != kLoginChallenge &&
property_name != kSendIq &&
property_name != kDesktopWidth &&
property_name != kDesktopHeight) {
*exception =
Expand Down Expand Up @@ -236,7 +246,7 @@ void ChromotingScriptableObject::SignalConnectionInfoChange() {

// Var() means call the object directly as a function rather than calling
// a method in the object.
cb.Call(Var(), 0, NULL, &exception);
cb.Call(Var(), &exception);

if (!exception.is_undefined())
LogDebugInfo(
Expand Down Expand Up @@ -266,23 +276,26 @@ void ChromotingScriptableObject::SignalLoginChallenge() {

// Var() means call the object directly as a function rather than calling
// a method in the object.
cb.Call(Var(), 0, NULL, &exception);
cb.Call(Var(), &exception);

if (!exception.is_undefined())
LogDebugInfo("Exception when invoking loginChallenge JS callback.");
}

void ChromotingScriptableObject::AttachXmppProxy(XmppProxy* xmpp_proxy) {
void ChromotingScriptableObject::AttachXmppProxy(PepperXmppProxy* xmpp_proxy) {
xmpp_proxy_ = xmpp_proxy;
}

void ChromotingScriptableObject::SendIq(const std::string& iq_request_xml) {
// TODO(ajwong): Do something smart here.
NOTIMPLEMENTED();
}
void ChromotingScriptableObject::SendIq(const std::string& message_xml) {
Var exception;
Var cb = GetProperty(Var(kSendIq), &exception);

void ChromotingScriptableObject::ReceiveIq(const std::string& iq_response_xml) {
xmpp_proxy_->ReceiveIq(iq_response_xml);
// Var() means call the object directly as a function rather than calling
// a method in the object.
cb.Call(Var(), Var(message_xml), &exception);

if (!exception.is_undefined())
LogDebugInfo("Exception when invoking loginChallenge JS callback.");
}

Var ChromotingScriptableObject::DoConnect(const std::vector<Var>& args,
Expand Down Expand Up @@ -318,6 +331,33 @@ Var ChromotingScriptableObject::DoConnect(const std::vector<Var>& args,
return Var();
}

Var ChromotingScriptableObject::DoConnectSandboxed(
const std::vector<Var>& args, Var* exception) {
if (args.size() != 2) {
*exception = Var("Usage: connectSandboxed(your_jid, host_jid)");
return Var();
}

std::string your_jid;
if (!args[0].is_string()) {
*exception = Var("your_jid must be a string.");
return Var();
}
your_jid = args[0].AsString();

std::string host_jid;
if (!args[1].is_string()) {
*exception = Var("host_jid must be a string.");
return Var();
}
host_jid = args[1].AsString();

VLOG(1) << "your_jid: " << your_jid << " and host_jid: " << host_jid;
instance_->ConnectSandboxed(your_jid, host_jid);

return Var();
}

Var ChromotingScriptableObject::DoDisconnect(const std::vector<Var>& args,
Var* exception) {
LogDebugInfo("Disconnecting from host.");
Expand Down Expand Up @@ -350,4 +390,21 @@ Var ChromotingScriptableObject::DoSubmitLogin(const std::vector<Var>& args,
return Var();
}

Var ChromotingScriptableObject::DoOnIq(const std::vector<Var>& args,
Var* exception) {
if (args.size() != 1) {
*exception = Var("Usage: onIq(response_xml)");
return Var();
}

if (!args[0].is_string()) {
*exception = Var("response_xml must be a string.");
return Var();
}

xmpp_proxy_->OnIq(args[0].AsString());

return Var();
}

} // namespace remoting
Loading

0 comments on commit 2db5310

Please sign in to comment.