summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/renderer/pepper_plugin_delegate_impl.cc13
-rw-r--r--ppapi/tests/test_query_policy.cc2
-rw-r--r--remoting/client/plugin/chromoting_instance.cc150
-rw-r--r--remoting/client/plugin/chromoting_instance.h37
-rw-r--r--remoting/protocol/connection_to_host.cc6
5 files changed, 171 insertions, 37 deletions
diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc
index dbeddbd..2ce1076 100644
--- a/content/renderer/pepper_plugin_delegate_impl.cc
+++ b/content/renderer/pepper_plugin_delegate_impl.cc
@@ -1324,16 +1324,9 @@ void PepperPluginDelegateImpl::SubscribeToPolicyUpdates(
webkit::ppapi::PluginInstance* instance) {
subscribed_to_policy_updates_.insert(instance);
- // Call by the PPP interface via continuation to avoid reentry issues
- // with being in the call chain that includes SubscribeToPolicyUpdates().
- //
- // TODO(ajwong): Hook this up into something that gets a real policy.
- MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&PepperPluginDelegateImpl::PublishInitialPolicy,
- AsWeakPtr(),
- make_scoped_refptr(instance),
- "{\"test_policy\": \"i like bananas\"}"));
+ // TODO(ajwong): Make this only send an update to the current instance,
+ // and not all subscribed plugin instances.
+ render_view_->RequestRemoteAccessClientFirewallTraversal();
}
std::string PepperPluginDelegateImpl::ResolveProxy(const GURL& url) {
diff --git a/ppapi/tests/test_query_policy.cc b/ppapi/tests/test_query_policy.cc
index 269a57c..6e8b4cb 100644
--- a/ppapi/tests/test_query_policy.cc
+++ b/ppapi/tests/test_query_policy.cc
@@ -50,7 +50,7 @@ std::string TestQueryPolicy::TestSubscribeToPolicyUpdates() {
// Wait for a response on PPP_PolicyUpdate_Dev.
GetTestingInterface()->RunMessageLoop(instance_->pp_instance());
- ASSERT_TRUE(g_received_policy == "{\"test_policy\": \"i like bananas\"}");
+ ASSERT_FALSE(g_received_policy.empty());
PASS();
}
diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc
index 7ec07a4..a9c1c1e 100644
--- a/remoting/client/plugin/chromoting_instance.cc
+++ b/remoting/client/plugin/chromoting_instance.cc
@@ -8,17 +8,20 @@
#include <vector>
#include "base/bind.h"
+#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/task.h"
#include "base/threading/thread.h"
+#include "base/values.h"
// TODO(sergeyu): We should not depend on renderer here. Instead P2P
// Pepper API should be used. Remove this dependency.
// crbug.com/74951
#include "content/renderer/p2p/ipc_network_manager.h"
#include "content/renderer/p2p/ipc_socket_factory.h"
+#include "ppapi/c/dev/ppb_query_policy_dev.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/rect.h"
@@ -49,13 +52,27 @@
namespace remoting {
+namespace {
+
+const char kClientFirewallTraversalPolicyName[] =
+ "remote_access.client_firewall_traversal";
+
+} // namespace
+
+PPP_PolicyUpdate_Dev ChromotingInstance::kPolicyUpdatedInterface = {
+ &ChromotingInstance::PolicyUpdatedThunk,
+};
+
const char* ChromotingInstance::kMimeType = "pepper-application/x-chromoting";
ChromotingInstance::ChromotingInstance(PP_Instance pp_instance)
: pp::InstancePrivate(pp_instance),
initialized_(false),
scale_to_fit_(false),
- logger_(this) {
+ logger_(this),
+ enable_client_nat_traversal_(false),
+ initial_policy_received_(false),
+ task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL);
RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
}
@@ -88,11 +105,41 @@ bool ChromotingInstance::Init(uint32_t argc,
// Start all the threads.
context_.Start();
+ SubscribeToNatTraversalPolicy();
+
+ // Create the chromoting objects that don't depend on the network connection.
+ view_.reset(new PepperView(this, &context_));
+ view_proxy_ = new PepperViewProxy(this, view_.get());
+ rectangle_decoder_ = new RectangleUpdateDecoder(
+ context_.decode_message_loop(), view_proxy_);
+
+ // Default to a medium grey.
+ view_->SetSolidFill(0xFFCDCDCD);
+
+ return true;
+}
+
+void ChromotingInstance::Connect(const ClientConfig& config) {
+ DCHECK(CurrentlyOnPluginThread());
+
+ // This can only happen at initialization if the Javascript connect call
+ // occurs before the enterprise policy is read. We are guaranteed that the
+ // enterprise policy is pushed at least once, we we delay the connect call.
+ if (!initial_policy_received_) {
+ logger_.Log(logging::LOG_INFO,
+ "Delaying connect until initial policy is read.");
+ delayed_connect_.reset(
+ task_factory_.NewRunnableMethod(&ChromotingInstance::Connect,
+ config));
+ return;
+ }
+
webkit::ppapi::PluginInstance* plugin_instance =
webkit::ppapi::ResourceTracker::Get()->GetInstance(pp_instance());
P2PSocketDispatcher* socket_dispatcher =
plugin_instance->delegate()->GetP2PSocketDispatcher();
+
IpcNetworkManager* network_manager = NULL;
IpcPacketSocketFactory* socket_factory = NULL;
PortAllocatorSessionFactory* session_factory =
@@ -106,28 +153,13 @@ bool ChromotingInstance::Init(uint32_t argc,
socket_factory = new IpcPacketSocketFactory(socket_dispatcher);
}
- // Create the chromoting objects.
- // TODO(sergeyu): Use firewall traversal policy settings here.
host_connection_.reset(new protocol::ConnectionToHost(
context_.network_message_loop(), network_manager, socket_factory,
- session_factory, false));
- view_.reset(new PepperView(this, &context_));
- view_proxy_ = new PepperViewProxy(this, view_.get());
- rectangle_decoder_ = new RectangleUpdateDecoder(
- context_.decode_message_loop(), view_proxy_);
+ session_factory, enable_client_nat_traversal_));
input_handler_.reset(new PepperInputHandler(&context_,
host_connection_.get(),
view_proxy_));
- // Default to a medium grey.
- view_->SetSolidFill(0xFFCDCDCD);
-
- return true;
-}
-
-void ChromotingInstance::Connect(const ClientConfig& config) {
- DCHECK(CurrentlyOnPluginThread());
-
client_.reset(new ChromotingClient(config, &context_, host_connection_.get(),
view_proxy_, rectangle_decoder_.get(),
input_handler_.get(), &logger_, NULL));
@@ -159,8 +191,12 @@ void ChromotingInstance::Disconnect() {
client_->Stop(base::Bind(&base::WaitableEvent::Signal,
base::Unretained(&done_event)));
done_event.Wait();
+ client_.reset();
}
+ input_handler_.reset();
+ host_connection_.reset();
+
GetScriptableObject()->SetConnectionInfo(STATUS_CLOSED, QUALITY_UNKNOWN);
}
@@ -189,6 +225,9 @@ void ChromotingInstance::DidChangeView(const pp::Rect& position,
bool ChromotingInstance::HandleInputEvent(const pp::InputEvent& event) {
DCHECK(CurrentlyOnPluginThread());
+ if (!input_handler_.get()) {
+ return false;
+ }
PepperInputHandler* pih
= static_cast<PepperInputHandler*>(input_handler_.get());
@@ -326,7 +365,84 @@ ChromotingStats* ChromotingInstance::GetStats() {
}
void ChromotingInstance::ReleaseAllKeys() {
+ if (!input_handler_.get()) {
+ return;
+ }
+
input_handler_->ReleaseAllKeys();
}
+// static
+void ChromotingInstance::PolicyUpdatedThunk(PP_Instance pp_instance,
+ PP_Var pp_policy_json) {
+ ChromotingInstance* instance = static_cast<ChromotingInstance*>(
+ pp::Module::Get()->InstanceForPPInstance(pp_instance));
+ std::string policy_json =
+ pp::Var(pp::Var::DontManage(), pp_policy_json).AsString();
+ instance->HandlePolicyUpdate(policy_json);
+}
+
+void ChromotingInstance::SubscribeToNatTraversalPolicy() {
+ pp::Module::Get()->AddPluginInterface(PPP_POLICY_UPDATE_DEV_INTERFACE,
+ &kPolicyUpdatedInterface);
+ const PPB_QueryPolicy_Dev* query_policy_interface =
+ static_cast<PPB_QueryPolicy_Dev const*>(
+ pp::Module::Get()->GetBrowserInterface(
+ PPB_QUERY_POLICY_DEV_INTERFACE));
+ query_policy_interface->SubscribeToPolicyUpdates(pp_instance());
+}
+
+bool ChromotingInstance::IsNatTraversalAllowed(
+ const std::string& policy_json) {
+ int error_code = base::JSONReader::JSON_NO_ERROR;
+ std::string error_message;
+ scoped_ptr<base::Value> policy(base::JSONReader::ReadAndReturnError(
+ policy_json, true, &error_code, &error_message));
+
+ if (!policy.get()) {
+ logger_.Log(logging::LOG_ERROR, "Error %d parsing policy: %s.",
+ error_code, error_message.c_str());
+ return false;
+ }
+
+ if (!policy->IsType(base::Value::TYPE_DICTIONARY)) {
+ logger_.Log(logging::LOG_ERROR, "Policy must be a dictionary");
+ return false;
+ }
+
+ base::DictionaryValue* dictionary =
+ static_cast<base::DictionaryValue*>(policy.get());
+ bool traversal_policy = false;
+ if (!dictionary->GetBoolean(kClientFirewallTraversalPolicyName,
+ &traversal_policy)) {
+ // Disable NAT traversal on any failure of reading the policy.
+ return false;
+ }
+
+ return traversal_policy;
+}
+
+void ChromotingInstance::HandlePolicyUpdate(const std::string policy_json) {
+ DCHECK(CurrentlyOnPluginThread());
+ bool traversal_policy = IsNatTraversalAllowed(policy_json);
+
+ // If the policy changes from traversal allowed, to traversal denied, we
+ // need to immediately drop all connections and redo the conneciton
+ // preparation.
+ if (traversal_policy == false &&
+ traversal_policy != enable_client_nat_traversal_) {
+ if (client_.get()) {
+ // This will delete the client and network related objects.
+ Disconnect();
+ }
+ }
+
+ initial_policy_received_ = true;
+ enable_client_nat_traversal_ = traversal_policy;
+
+ if (delayed_connect_.get()) {
+ RunTaskOnPluginThread(delayed_connect_.release());
+ }
+}
+
} // namespace remoting
diff --git a/remoting/client/plugin/chromoting_instance.h b/remoting/client/plugin/chromoting_instance.h
index 838f9e9..787713a 100644
--- a/remoting/client/plugin/chromoting_instance.h
+++ b/remoting/client/plugin/chromoting_instance.h
@@ -12,9 +12,11 @@
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
+#include "ppapi/c/dev/ppp_policy_update_dev.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/pp_resource.h"
+#include "ppapi/c/pp_var.h"
#include "ppapi/cpp/var.h"
#include "ppapi/cpp/private/instance_private.h"
#include "remoting/client/client_context.h"
@@ -62,19 +64,23 @@ class ChromotingInstance : public pp::InstancePrivate {
explicit ChromotingInstance(PP_Instance instance);
virtual ~ChromotingInstance();
- virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
- virtual void Connect(const ClientConfig& config);
- virtual bool HandleInputEvent(const pp::InputEvent& event);
- virtual void Disconnect();
- virtual pp::Var GetInstanceObject();
-
// pp::Instance interface.
virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip)
OVERRIDE;
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[])
+ OVERRIDE;
+ virtual bool HandleInputEvent(const pp::InputEvent& event) OVERRIDE;
+
+ // pp::InstancePrivate interface.
+ virtual pp::Var GetInstanceObject() OVERRIDE;
// Convenience wrapper to get the ChromotingScriptableObject.
ChromotingScriptableObject* GetScriptableObject();
+ // Initiates and cancels connections.
+ void Connect(const ClientConfig& config);
+ void Disconnect();
+
// Called by ChromotingScriptableObject to provide username and password.
void SubmitLoginInfo(const std::string& username,
const std::string& password);
@@ -96,6 +102,13 @@ class ChromotingInstance : public pp::InstancePrivate {
private:
FRIEND_TEST_ALL_PREFIXES(ChromotingInstanceTest, TestCaseSetup);
+ static PPP_PolicyUpdate_Dev kPolicyUpdatedInterface;
+ static void PolicyUpdatedThunk(PP_Instance pp_instance,
+ PP_Var pp_policy_json);
+ void SubscribeToNatTraversalPolicy();
+ bool IsNatTraversalAllowed(const std::string& policy_json);
+ void HandlePolicyUpdate(const std::string policy_json);
+
bool initialized_;
ClientContext context_;
@@ -129,6 +142,18 @@ class ChromotingInstance : public pp::InstancePrivate {
// This wraps a ChromotingScriptableObject in a pp::Var.
pp::Var instance_object_;
+ // Controls if this instance of the plugin should attempt to bridge
+ // firewalls.
+ bool enable_client_nat_traversal_;
+
+ // True when the initial policy is received. Used to avoid taking
+ // action before the browser has informed the plugin about its policy
+ // settings.
+ bool initial_policy_received_;
+
+ ScopedRunnableMethodFactory<ChromotingInstance> task_factory_;
+ scoped_ptr<Task> delayed_connect_;
+
DISALLOW_COPY_AND_ASSIGN(ChromotingInstance);
};
diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc
index fe75cfe..580f198 100644
--- a/remoting/protocol/connection_to_host.cc
+++ b/remoting/protocol/connection_to_host.cc
@@ -115,9 +115,6 @@ void ConnectionToHost::InitSession() {
session_manager_.reset(session_manager);
session_manager_->Init(
local_jid_, signal_strategy_.get(), this, NULL, "", allow_nat_traversal_);
-
- // Set the shared-secret for securing SSL channels.
- session_->set_shared_secret(access_code_);
}
const SessionConfig* ConnectionToHost::config() {
@@ -154,6 +151,9 @@ void ConnectionToHost::OnSessionManagerInitialized() {
session_.reset(session_manager_->Connect(
host_jid_, host_public_key_, client_token, candidate_config,
NewCallback(this, &ConnectionToHost::OnSessionStateChange)));
+
+ // Set the shared-secret for securing SSL channels.
+ session_->set_shared_secret(access_code_);
}
void ConnectionToHost::OnIncomingSession(