diff options
author | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-12 19:38:55 +0000 |
---|---|---|
committer | dmichael@chromium.org <dmichael@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-12 19:38:55 +0000 |
commit | 73097564b57bad21efbb72e49a0edf0d13e9c249 (patch) | |
tree | 3f0e4f402f6fc1252765260241199519a94ce5e3 | |
parent | a21d8087f7ca0a8ccf2d07344b7dcfa34d455886 (diff) | |
download | chromium_src-73097564b57bad21efbb72e49a0edf0d13e9c249.zip chromium_src-73097564b57bad21efbb72e49a0edf0d13e9c249.tar.gz chromium_src-73097564b57bad21efbb72e49a0edf0d13e9c249.tar.bz2 |
Reland 9034035: Make it possible to have 1 PpapiGlobals per thread.
Original CL: r117399, http://codereview.chromium.org/9034035/
Reverted in r117414, http://codereview.chromium.org/9139054/ due to a static initializer.
This is the same as r117399 except using a LazyInstance to eliminate the static initializer.
BUG=
TEST=
TBR=dmichael@chromium.org
Review URL: http://codereview.chromium.org/9187055
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117475 0039d316-1c4b-4281-b951-d872f2087c98
27 files changed, 351 insertions, 223 deletions
diff --git a/ppapi/proxy/host_dispatcher.cc b/ppapi/proxy/host_dispatcher.cc index 1205189..efd1f56 100644 --- a/ppapi/proxy/host_dispatcher.cc +++ b/ppapi/proxy/host_dispatcher.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. @@ -71,9 +71,7 @@ HostDispatcher::HostDispatcher(base::ProcessHandle remote_process_handle, g_module_to_dispatcher = new ModuleToDispatcherMap; (*g_module_to_dispatcher)[pp_module_] = this; - const PPB_Var* var_interface = - static_cast<const PPB_Var*>(local_get_interface(PPB_VAR_INTERFACE)); - SetSerializationRules(new HostVarSerializationRules(var_interface, module)); + SetSerializationRules(new HostVarSerializationRules(module)); ppb_proxy_ = reinterpret_cast<const PPB_Proxy_Private*>( local_get_interface(PPB_PROXY_PRIVATE_INTERFACE)); diff --git a/ppapi/proxy/host_var_serialization_rules.cc b/ppapi/proxy/host_var_serialization_rules.cc index ae6b7f7..3f11090 100644 --- a/ppapi/proxy/host_var_serialization_rules.cc +++ b/ppapi/proxy/host_var_serialization_rules.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. @@ -6,15 +6,19 @@ #include "base/logging.h" #include "ppapi/c/ppb_var.h" +#include "ppapi/shared_impl/ppapi_globals.h" +#include "ppapi/shared_impl/var.h" +#include "ppapi/shared_impl/var_tracker.h" + +using ppapi::PpapiGlobals; +using ppapi::StringVar; +using ppapi::VarTracker; namespace ppapi { namespace proxy { -HostVarSerializationRules::HostVarSerializationRules( - const PPB_Var* var_interface, - PP_Module pp_module) - : var_interface_(var_interface), - pp_module_(pp_module) { +HostVarSerializationRules::HostVarSerializationRules(PP_Module pp_module) + : pp_module_(pp_module) { } HostVarSerializationRules::~HostVarSerializationRules() { @@ -31,18 +35,15 @@ PP_Var HostVarSerializationRules::BeginReceiveCallerOwned( const PP_Var& var, const std::string* str_val, Dispatcher* /* dispatcher */) { - if (var.type == PP_VARTYPE_STRING) { - // Convert the string to the context of the current process. - return var_interface_->VarFromUtf8(str_val->c_str(), - static_cast<uint32_t>(str_val->size())); - } + if (var.type == PP_VARTYPE_STRING) + return StringVar::StringToPPVar(*str_val); return var; } void HostVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) { if (var.type == PP_VARTYPE_STRING) { // Destroy the string BeginReceiveCallerOwned created above. - var_interface_->Release(var); + PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var); } } @@ -51,13 +52,12 @@ PP_Var HostVarSerializationRules::ReceivePassRef(const PP_Var& var, Dispatcher* /* dispatcher */) { if (var.type == PP_VARTYPE_STRING) { // Convert the string to the context of the current process. - return var_interface_->VarFromUtf8(str_val.c_str(), - static_cast<uint32_t>(str_val.size())); + return StringVar::StringToPPVar(str_val); } // See PluginVarSerialization::BeginSendPassRef for an example. if (var.type == PP_VARTYPE_OBJECT) - var_interface_->AddRef(var); + PpapiGlobals::Get()->GetVarTracker()->AddRefVar(var); return var; } @@ -83,13 +83,13 @@ void HostVarSerializationRules::VarToString(const PP_Var& var, // This could be optimized to avoid an extra string copy by going to a lower // level of the browser's implementation of strings where we already have // a std::string. - uint32_t len = 0; - const char* data = var_interface_->VarToUtf8(var, &len); - str->assign(data, len); + StringVar* string_var = StringVar::FromPPVar(var); + if (string_var) + *str = string_var->value(); } void HostVarSerializationRules::ReleaseObjectRef(const PP_Var& var) { - var_interface_->Release(var); + PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var); } } // namespace proxy diff --git a/ppapi/proxy/host_var_serialization_rules.h b/ppapi/proxy/host_var_serialization_rules.h index 9c4db2e..bbbb3d7 100644 --- a/ppapi/proxy/host_var_serialization_rules.h +++ b/ppapi/proxy/host_var_serialization_rules.h @@ -18,8 +18,7 @@ namespace proxy { // Implementation of the VarSerializationRules interface for the host side. class HostVarSerializationRules : public VarSerializationRules { public: - HostVarSerializationRules(const PPB_Var* var_interface, - PP_Module pp_module); + HostVarSerializationRules(PP_Module pp_module); ~HostVarSerializationRules(); // VarSerialization implementation. @@ -40,7 +39,6 @@ class HostVarSerializationRules : public VarSerializationRules { // string object. void VarToString(const PP_Var& var, std::string* str); - const PPB_Var* var_interface_; PP_Module pp_module_; DISALLOW_COPY_AND_ASSIGN(HostVarSerializationRules); diff --git a/ppapi/proxy/plugin_globals.cc b/ppapi/proxy/plugin_globals.cc index 664fbeb..360f221 100644 --- a/ppapi/proxy/plugin_globals.cc +++ b/ppapi/proxy/plugin_globals.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. @@ -19,8 +19,15 @@ PluginGlobals::PluginGlobals() plugin_globals_ = this; } +PluginGlobals::PluginGlobals(ForTest for_test) + : ppapi::PpapiGlobals(for_test), + plugin_proxy_delegate_(NULL), + callback_tracker_(new CallbackTracker) { + DCHECK(!plugin_globals_); +} + PluginGlobals::~PluginGlobals() { - DCHECK(plugin_globals_ == this); + DCHECK(plugin_globals_ == this || !plugin_globals_); plugin_globals_ = NULL; } @@ -51,5 +58,17 @@ PP_Module PluginGlobals::GetModuleForInstance(PP_Instance instance) { return 0; } +base::Lock* PluginGlobals::GetProxyLock() { +#ifdef ENABLE_PEPPER_THREADING + return &proxy_lock_; +#else + return NULL; +#endif +} + +bool PluginGlobals::IsPluginGlobals() const { + return true; +} + } // namespace proxy } // namespace ppapi diff --git a/ppapi/proxy/plugin_globals.h b/ppapi/proxy/plugin_globals.h index ffcf01e..0b47616 100644 --- a/ppapi/proxy/plugin_globals.h +++ b/ppapi/proxy/plugin_globals.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. @@ -6,6 +6,7 @@ #define PPAPI_PROXY_PLUGIN_GLOBALS_H_ #include "base/compiler_specific.h" +#include "base/synchronization/lock.h" #include "ppapi/proxy/plugin_resource_tracker.h" #include "ppapi/proxy/plugin_var_tracker.h" #include "ppapi/proxy/ppapi_proxy_export.h" @@ -20,12 +21,16 @@ class PluginProxyDelegate; class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals { public: PluginGlobals(); + PluginGlobals(PpapiGlobals::ForTest); virtual ~PluginGlobals(); // Getter for the global singleton. Generally, you should use // PpapiGlobals::Get() when possible. Use this only when you need some // plugin-specific functionality. - inline static PluginGlobals* Get() { return plugin_globals_; } + inline static PluginGlobals* Get() { + DCHECK(PpapiGlobals::Get()->IsPluginGlobals()); + return static_cast<PluginGlobals*>(PpapiGlobals::Get()); + } // PpapiGlobals implementation. virtual ResourceTracker* GetResourceTracker() OVERRIDE; @@ -35,6 +40,7 @@ class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals { virtual FunctionGroupBase* GetFunctionAPI(PP_Instance inst, ApiID id) OVERRIDE; virtual PP_Module GetModuleForInstance(PP_Instance instance) OVERRIDE; + virtual base::Lock* GetProxyLock() OVERRIDE; // Getters for the plugin-specific versions. PluginResourceTracker* plugin_resource_tracker() { @@ -53,12 +59,16 @@ class PPAPI_PROXY_EXPORT PluginGlobals : public PpapiGlobals { } private: + // PpapiGlobals overrides. + virtual bool IsPluginGlobals() const OVERRIDE; + static PluginGlobals* plugin_globals_; PluginProxyDelegate* plugin_proxy_delegate_; PluginResourceTracker plugin_resource_tracker_; PluginVarTracker plugin_var_tracker_; scoped_refptr<CallbackTracker> callback_tracker_; + base::Lock proxy_lock_; DISALLOW_COPY_AND_ASSIGN(PluginGlobals); }; diff --git a/ppapi/proxy/plugin_resource_tracker.cc b/ppapi/proxy/plugin_resource_tracker.cc index 3fee320..ac28de3 100644 --- a/ppapi/proxy/plugin_resource_tracker.cc +++ b/ppapi/proxy/plugin_resource_tracker.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. @@ -18,17 +18,9 @@ namespace ppapi { namespace proxy { PluginResourceTracker::PluginResourceTracker() { -#ifdef ENABLE_PEPPER_THREADING - // Set the global proxy lock, since the plugin-side of the proxy needs to be - // synchronized. - ppapi::ProxyLock::Set(&proxy_lock_); -#endif } PluginResourceTracker::~PluginResourceTracker() { -#ifdef ENABLE_PEPPER_THREADING - ppapi::ProxyLock::Reset(); -#endif } PP_Resource PluginResourceTracker::PluginResourceForHostResource( diff --git a/ppapi/proxy/plugin_resource_tracker.h b/ppapi/proxy/plugin_resource_tracker.h index 35c2385..6bed72f 100644 --- a/ppapi/proxy/plugin_resource_tracker.h +++ b/ppapi/proxy/plugin_resource_tracker.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. @@ -9,7 +9,6 @@ #include <utility> #include "base/compiler_specific.h" -#include "base/synchronization/lock.h" #include "ppapi/c/pp_completion_callback.h" #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_stdint.h" @@ -45,9 +44,6 @@ class PPAPI_PROXY_EXPORT PluginResourceTracker : public ResourceTracker { typedef std::map<HostResource, PP_Resource> HostResourceMap; HostResourceMap host_resource_map_; - // The global lock for the plugin side of the proxy. - base::Lock proxy_lock_; - DISALLOW_COPY_AND_ASSIGN(PluginResourceTracker); }; diff --git a/ppapi/proxy/plugin_var_serialization_rules.cc b/ppapi/proxy/plugin_var_serialization_rules.cc index a4eea5b..2e92dd5 100644 --- a/ppapi/proxy/plugin_var_serialization_rules.cc +++ b/ppapi/proxy/plugin_var_serialization_rules.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. @@ -85,7 +85,7 @@ PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var, // plugin code started to return a value, which means it gets another ref // on behalf of the caller. This needs to be transferred to the plugin and // folded in to its set of refs it maintains (with one ref representing all - // fo them in the browser). + // of them in the browser). if (var.type == PP_VARTYPE_OBJECT) { DCHECK(dispatcher->IsPlugin()); return var_tracker_->ReceiveObjectPassRef( diff --git a/ppapi/proxy/plugin_var_tracker.cc b/ppapi/proxy/plugin_var_tracker.cc index a7c83f3..525b1a3 100644 --- a/ppapi/proxy/plugin_var_tracker.cc +++ b/ppapi/proxy/plugin_var_tracker.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. @@ -141,21 +141,6 @@ void PluginVarTracker::ReleaseHostObject(PluginDispatcher* dispatcher, ReleaseVar(found->second); } -int PluginVarTracker::GetRefCountForObject(const PP_Var& plugin_object) { - VarMap::iterator found = GetLiveVar(plugin_object); - if (found == live_vars_.end()) - return -1; - return found->second.ref_count; -} - -int PluginVarTracker::GetTrackedWithNoReferenceCountForObject( - const PP_Var& plugin_object) { - VarMap::iterator found = GetLiveVar(plugin_object); - if (found == live_vars_.end()) - return -1; - return found->second.track_with_no_reference_count; -} - ArrayBufferVar* PluginVarTracker::CreateArrayBuffer(uint32 size_in_bytes) { return new PluginArrayBufferVar(size_in_bytes); } diff --git a/ppapi/proxy/plugin_var_tracker.h b/ppapi/proxy/plugin_var_tracker.h index c2ede10..cafb3ab 100644 --- a/ppapi/proxy/plugin_var_tracker.h +++ b/ppapi/proxy/plugin_var_tracker.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. @@ -56,12 +56,6 @@ class PPAPI_PROXY_EXPORT PluginVarTracker : public VarTracker { void ReleaseHostObject(PluginDispatcher* dispatcher, const PP_Var& host_object); - // Retrieves the internal reference counts for testing. Returns 0 if we - // know about the object but the corresponding value is 0, or -1 if the - // given object ID isn't in our map. - int GetRefCountForObject(const PP_Var& plugin_object); - int GetTrackedWithNoReferenceCountForObject(const PP_Var& plugin_object); - private: // VarTracker protected overrides. virtual int32 AddVarInternal(Var* var, AddVarRefMode mode) OVERRIDE; diff --git a/ppapi/proxy/ppapi_proxy_test.cc b/ppapi/proxy/ppapi_proxy_test.cc index 8ab8c36..15dc967 100644 --- a/ppapi/proxy/ppapi_proxy_test.cc +++ b/ppapi/proxy/ppapi_proxy_test.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. @@ -139,7 +139,8 @@ bool ProxyTestHarnessBase::SupportsInterface(const char* name) { // PluginProxyTestHarness ------------------------------------------------------ -PluginProxyTestHarness::PluginProxyTestHarness() { +PluginProxyTestHarness::PluginProxyTestHarness() + : plugin_globals_(PpapiGlobals::ForTest()) { } PluginProxyTestHarness::~PluginProxyTestHarness() { @@ -151,6 +152,7 @@ Dispatcher* PluginProxyTestHarness::GetDispatcher() { void PluginProxyTestHarness::SetUpHarness() { // These must be first since the dispatcher set-up uses them. + PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals()); resource_tracker().DidCreateInstance(pp_instance()); plugin_dispatcher_.reset(new PluginDispatcher( @@ -166,6 +168,7 @@ void PluginProxyTestHarness::SetUpHarnessWithChannel( base::WaitableEvent* shutdown_event, bool is_client) { // These must be first since the dispatcher set-up uses them. + PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals()); resource_tracker().DidCreateInstance(pp_instance()); plugin_delegate_mock_.Init(ipc_message_loop, shutdown_event); @@ -248,7 +251,8 @@ void PluginProxyTest::TearDown() { // HostProxyTestHarness -------------------------------------------------------- -HostProxyTestHarness::HostProxyTestHarness() { +HostProxyTestHarness::HostProxyTestHarness() + : host_globals_(PpapiGlobals::ForTest()) { } HostProxyTestHarness::~HostProxyTestHarness() { @@ -259,6 +263,8 @@ Dispatcher* HostProxyTestHarness::GetDispatcher() { } void HostProxyTestHarness::SetUpHarness() { + // These must be first since the dispatcher set-up uses them. + PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals()); host_dispatcher_.reset(new HostDispatcher( base::Process::Current().handle(), pp_module(), @@ -272,7 +278,10 @@ void HostProxyTestHarness::SetUpHarnessWithChannel( base::MessageLoopProxy* ipc_message_loop, base::WaitableEvent* shutdown_event, bool is_client) { + // These must be first since the dispatcher set-up uses them. + PpapiGlobals::SetPpapiGlobalsOnThreadForTest(GetGlobals()); delegate_mock_.Init(ipc_message_loop, shutdown_event); + host_dispatcher_.reset(new HostDispatcher( base::Process::Current().handle(), pp_module(), @@ -345,7 +354,6 @@ void TwoWayTest::SetUp() { IPC::ChannelHandle handle; handle.name = "TwoWayTestChannel"; - base::WaitableEvent remote_harness_set_up(true, false); plugin_thread_.message_loop_proxy()->PostTask( FROM_HERE, diff --git a/ppapi/proxy/ppapi_proxy_test.h b/ppapi/proxy/ppapi_proxy_test.h index 2a612ed..5816188 100644 --- a/ppapi/proxy/ppapi_proxy_test.h +++ b/ppapi/proxy/ppapi_proxy_test.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. @@ -17,6 +17,7 @@ #include "ppapi/proxy/plugin_proxy_delegate.h" #include "ppapi/proxy/plugin_resource_tracker.h" #include "ppapi/proxy/plugin_var_tracker.h" +#include "ppapi/shared_impl/test_globals.h" #include "testing/gtest/include/gtest/gtest.h" namespace ppapi { @@ -33,6 +34,7 @@ class ProxyTestHarnessBase { PP_Instance pp_instance() const { return pp_instance_; } IPC::TestSink& sink() { return sink_; } + virtual PpapiGlobals* GetGlobals() = 0; // Returns either the plugin or host dispatcher, depending on the test. virtual Dispatcher* GetDispatcher() = 0; @@ -88,6 +90,7 @@ class PluginProxyTestHarness : public ProxyTestHarnessBase { } // ProxyTestHarnessBase implementation. + virtual PpapiGlobals* GetGlobals() { return &plugin_globals_; } virtual Dispatcher* GetDispatcher(); virtual void SetUpHarness(); virtual void SetUpHarnessWithChannel(const IPC::ChannelHandle& channel_handle, @@ -157,8 +160,15 @@ class HostProxyTestHarness : public ProxyTestHarnessBase { virtual ~HostProxyTestHarness(); HostDispatcher* host_dispatcher() { return host_dispatcher_.get(); } + ResourceTracker& resource_tracker() { + return *host_globals_.GetResourceTracker(); + } + VarTracker& var_tracker() { + return *host_globals_.GetVarTracker(); + } // ProxyTestBase implementation. + virtual PpapiGlobals* GetGlobals() { return &host_globals_; } virtual Dispatcher* GetDispatcher(); virtual void SetUpHarness(); virtual void SetUpHarnessWithChannel(const IPC::ChannelHandle& channel_handle, @@ -191,6 +201,7 @@ class HostProxyTestHarness : public ProxyTestHarnessBase { }; private: + ppapi::TestGlobals host_globals_; scoped_ptr<HostDispatcher> host_dispatcher_; DelegateMock delegate_mock_; }; diff --git a/ppapi/proxy/ppb_var_unittest.cc b/ppapi/proxy/ppb_var_unittest.cc index bf6147d..74ed453 100644 --- a/ppapi/proxy/ppb_var_unittest.cc +++ b/ppapi/proxy/ppb_var_unittest.cc @@ -10,6 +10,7 @@ #include "ppapi/c/pp_var.h" #include "ppapi/c/ppb_var.h" #include "ppapi/proxy/ppapi_proxy_test.h" +#include "ppapi/shared_impl/ppapi_globals.h" #include "ppapi/shared_impl/ppb_var_shared.h" namespace { @@ -96,12 +97,13 @@ class CreateVarThreadDelegate : public base::PlatformThread::Delegate { // read the var back out to |strings_out[i]|. CreateVarThreadDelegate(PP_Module pp_module, const std::string* strings_in, PP_Var* vars_out, std::string* strings_out, - size_t size) + size_t size, PpapiGlobals* globals) : pp_module_(pp_module), strings_in_(strings_in), vars_out_(vars_out), - strings_out_(strings_out), size_(size) { + strings_out_(strings_out), size_(size), globals_(globals) { } virtual ~CreateVarThreadDelegate() {} virtual void ThreadMain() { + PpapiGlobals::SetPpapiGlobalsOnThreadForTest(globals_); const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1(); for (size_t i = 0; i < size_; ++i) { vars_out_[i] = ppb_var->VarFromUtf8(strings_in_[i].c_str(), @@ -115,16 +117,20 @@ class CreateVarThreadDelegate : public base::PlatformThread::Delegate { PP_Var* vars_out_; std::string* strings_out_; size_t size_; + PpapiGlobals* globals_; }; // A thread that will increment and decrement the reference count of every var // multiple times. class ChangeRefVarThreadDelegate : public base::PlatformThread::Delegate { public: - ChangeRefVarThreadDelegate(const std::vector<PP_Var>& vars) : vars_(vars) { + ChangeRefVarThreadDelegate(const std::vector<PP_Var>& vars, + PpapiGlobals* globals) + : vars_(vars), globals_(globals) { } virtual ~ChangeRefVarThreadDelegate() {} virtual void ThreadMain() { + PpapiGlobals::SetPpapiGlobalsOnThreadForTest(globals_); const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1(); // Increment and decrement the reference count for each var kRefsToAdd // times. Note that we always AddRef once before doing the matching Release, @@ -144,15 +150,19 @@ class ChangeRefVarThreadDelegate : public base::PlatformThread::Delegate { } private: std::vector<PP_Var> vars_; + PpapiGlobals* globals_; }; // A thread that will decrement the reference count of every var once. class RemoveRefVarThreadDelegate : public base::PlatformThread::Delegate { public: - RemoveRefVarThreadDelegate(const std::vector<PP_Var>& vars) : vars_(vars) { + RemoveRefVarThreadDelegate(const std::vector<PP_Var>& vars, + PpapiGlobals* globals) + : vars_(vars), globals_(globals) { } virtual ~RemoveRefVarThreadDelegate() {} virtual void ThreadMain() { + PpapiGlobals::SetPpapiGlobalsOnThreadForTest(globals_); const PPB_Var* ppb_var = ppapi::PPB_Var_Shared::GetVarInterface1_1(); for (size_t i = 0; i < kNumStrings; ++i) { ppb_var->Release(vars_[i]); @@ -160,6 +170,7 @@ class RemoveRefVarThreadDelegate : public base::PlatformThread::Delegate { } private: std::vector<PP_Var> vars_; + PpapiGlobals* globals_; }; } // namespace @@ -186,7 +197,8 @@ TEST_F(PPB_VarTest, DISABLED_Threads) { &vars_[slice_start], &strings_out[slice_start], std::min(strings_per_thread, - kNumStrings - slice_start))); + kNumStrings - slice_start), + GetGlobals())); } // Now run then join all the threads. for (size_t i = 0; i < kNumThreads; ++i) @@ -201,7 +213,8 @@ TEST_F(PPB_VarTest, DISABLED_Threads) { std::vector<base::PlatformThreadHandle> change_ref_var_threads(kNumThreads); std::vector<ChangeRefVarThreadDelegate> change_ref_var_delegates; for (size_t i = 0; i < kNumThreads; ++i) - change_ref_var_delegates.push_back(ChangeRefVarThreadDelegate(vars_)); + change_ref_var_delegates.push_back( + ChangeRefVarThreadDelegate(vars_, GetGlobals())); for (size_t i = 0; i < kNumThreads; ++i) { base::PlatformThread::Create(0, &change_ref_var_delegates[i], &change_ref_var_threads[i]); @@ -224,7 +237,8 @@ TEST_F(PPB_VarTest, DISABLED_Threads) { std::vector<base::PlatformThreadHandle> remove_ref_var_threads(kNumThreads); std::vector<RemoveRefVarThreadDelegate> remove_ref_var_delegates; for (size_t i = 0; i < kNumThreads; ++i) - remove_ref_var_delegates.push_back(RemoveRefVarThreadDelegate(vars_)); + remove_ref_var_delegates.push_back( + RemoveRefVarThreadDelegate(vars_, GetGlobals())); for (size_t i = 0; i < kNumThreads; ++i) { base::PlatformThread::Create(0, &remove_ref_var_delegates[i], &remove_ref_var_threads[i]); diff --git a/ppapi/proxy/ppp_instance_private_proxy_unittest.cc b/ppapi/proxy/ppp_instance_private_proxy_unittest.cc index ea57ec1..6b87f12 100644 --- a/ppapi/proxy/ppp_instance_private_proxy_unittest.cc +++ b/ppapi/proxy/ppp_instance_private_proxy_unittest.cc @@ -1,7 +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. +#include "base/bind.h" +#include "base/message_loop.h" +#include "base/test/test_timeouts.h" +#include "base/time.h" #include "ppapi/c/dev/ppb_var_deprecated.h" #include "ppapi/c/dev/ppp_class_deprecated.h" #include "ppapi/c/pp_var.h" @@ -10,18 +14,31 @@ #include "ppapi/c/private/ppp_instance_private.h" #include "ppapi/proxy/host_dispatcher.h" #include "ppapi/proxy/ppapi_proxy_test.h" +#include "ppapi/shared_impl/ppb_var_shared.h" +#include "ppapi/shared_impl/var.h" namespace ppapi { + +// A fake version of NPObjectVar for testing. +class NPObjectVar : public ppapi::Var { + public: + NPObjectVar() {} + virtual ~NPObjectVar() {} + + // Var overrides. + virtual NPObjectVar* AsNPObjectVar() OVERRIDE { return this; } + virtual PP_VarType GetType() const OVERRIDE { return PP_VARTYPE_OBJECT; } +}; + namespace proxy { namespace { const PP_Instance kInstance = 0xdeadbeef; -PP_Var MakeObjectVar(int64_t object_id) { - PP_Var ret; - ret.type = PP_VARTYPE_OBJECT; - ret.value.as_id = object_id; - return ret; +PP_Var GetPPVarNoAddRef(Var* var) { + PP_Var var_to_return = var->GetPPVar(); + PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(var_to_return); + return var_to_return; } PluginDispatcher* plugin_dispatcher = NULL; @@ -40,7 +57,8 @@ PP_Var instance_obj; PP_Var GetInstanceObject(PP_Instance /*instance*/) { // The 1 ref we got from CreateObject will be passed to the host. We want to // have a ref of our own. - plugin_var_deprecated_if()->AddRef(instance_obj); + printf("GetInstanceObject called\n"); + PpapiGlobals::Get()->GetVarTracker()->AddRefVar(instance_obj); return instance_obj; } @@ -67,41 +85,19 @@ void DidDestroy(PP_Instance /*instance*/) { PPP_Instance_1_0 ppp_instance_mock = { &DidCreate, &DidDestroy }; -} // namespace - // Mock PPB_Var_Deprecated, so that we can emulate creating an Object Var. -std::map<int64_t, int> id_refcount_map; -void AddRefVar(PP_Var var) { - CHECK(var.type >= PP_VARTYPE_STRING); // Must be a ref-counted type. - CHECK(id_refcount_map.find(var.value.as_id) != id_refcount_map.end()); - ++id_refcount_map[var.value.as_id]; -} - -void ReleaseVar(PP_Var var) { - CHECK(var.type >= PP_VARTYPE_STRING); // Must be a ref-counted type. - std::map<int64_t, int>::iterator iter = id_refcount_map.find(var.value.as_id); - CHECK(iter != id_refcount_map.end()); - CHECK(iter->second > 0); - if (--(iter->second) == 0) - id_refcount_map.erase(iter); -} - -PP_Var CreateObject(PP_Instance instance, +PP_Var CreateObject(PP_Instance /*instance*/, const PPP_Class_Deprecated* /*ppp_class*/, void* /*ppp_class_data*/) { - static int64_t last_id = 0; - ++last_id; - // Set the refcount to 0. It should really be 1, but that ref gets passed to - // the plugin immediately (and we don't emulate all of that behavior here). - id_refcount_map[last_id] = 0; - return MakeObjectVar(last_id); + NPObjectVar* obj_var = new NPObjectVar; + return obj_var->GetPPVar(); } const PPB_Var_Deprecated ppb_var_deprecated_mock = { - &AddRefVar, - &ReleaseVar, - NULL, // VarFromUtf8 - NULL, // VarToUtf8 + PPB_Var_Shared::GetVarInterface1_0()->AddRef, + PPB_Var_Shared::GetVarInterface1_0()->Release, + PPB_Var_Shared::GetVarInterface1_0()->VarFromUtf8, + PPB_Var_Shared::GetVarInterface1_0()->VarToUtf8, NULL, // HasProperty NULL, // HasMethod NULL, // GetProperty @@ -114,7 +110,7 @@ const PPB_Var_Deprecated ppb_var_deprecated_mock = { &CreateObject }; -const PPB_Var ppb_var_mock = { &AddRefVar, &ReleaseVar }; +} // namespace class PPP_Instance_Private_ProxyTest : public TwoWayTest { public: @@ -126,8 +122,6 @@ class PPP_Instance_Private_ProxyTest : public TwoWayTest { &ppp_instance_mock); host().RegisterTestInterface(PPB_VAR_DEPRECATED_INTERFACE, &ppb_var_deprecated_mock); - host().RegisterTestInterface(PPB_VAR_INTERFACE, - &ppb_var_mock); } }; @@ -146,44 +140,43 @@ TEST_F(PPP_Instance_Private_ProxyTest, PPPInstancePrivate) { static_cast<const PPP_Instance_Private*>( host().host_dispatcher()->GetProxiedInterface( PPP_INSTANCE_PRIVATE_INTERFACE)); - const PPP_Instance_1_0* ppp_instance = static_cast<const PPP_Instance_1_0*>( + const PPP_Instance_1_1* ppp_instance = static_cast<const PPP_Instance_1_1*>( host().host_dispatcher()->GetProxiedInterface( - PPP_INSTANCE_INTERFACE_1_0)); + PPP_INSTANCE_INTERFACE_1_1)); // Initialize an Instance, so that the plugin-side machinery will work // properly. EXPECT_EQ(PP_TRUE, ppp_instance->DidCreate(kInstance, 0, NULL, NULL)); - // Now instance_obj is valid and should have a ref-count of 1. - PluginVarTracker& plugin_var_tracker = - *PluginGlobals::Get()->plugin_var_tracker(); // Check the plugin-side reference count. - EXPECT_EQ(1, plugin_var_tracker.GetRefCountForObject(instance_obj)); - // Check the host-side var and reference count. - ASSERT_EQ(1u, id_refcount_map.size()); - EXPECT_EQ(plugin_var_tracker.GetHostObject(instance_obj).value.as_id, - id_refcount_map.begin()->first); - EXPECT_EQ(0, id_refcount_map.begin()->second); + EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj)); + // Check the host-side var exists with the expected id and has 1 refcount (the + // refcount on behalf of the plugin). + int32 expected_host_id = + plugin().var_tracker().GetHostObject(instance_obj).value.as_id; + Var* host_var = host().var_tracker().GetVar(expected_host_id); + ASSERT_TRUE(host_var); + EXPECT_EQ( + 1, + host().var_tracker().GetRefCountForObject(GetPPVarNoAddRef(host_var))); // Call from the browser side to get the instance object. - PP_Var host_obj = ppp_instance_private->GetInstanceObject(kInstance); - EXPECT_EQ(instance_obj.type, host_obj.type); - EXPECT_EQ(host_obj.value.as_id, - plugin_var_tracker.GetHostObject(instance_obj).value.as_id); - EXPECT_EQ(1, plugin_var_tracker.GetRefCountForObject(instance_obj)); - ASSERT_EQ(1u, id_refcount_map.size()); - // The browser should be passed a reference. - EXPECT_EQ(1, id_refcount_map.begin()->second); + PP_Var host_pp_var = ppp_instance_private->GetInstanceObject(kInstance); + EXPECT_EQ(instance_obj.type, host_pp_var.type); + EXPECT_EQ(host_pp_var.value.as_id, expected_host_id); + EXPECT_EQ(1, plugin().var_tracker().GetRefCountForObject(instance_obj)); + // A reference is passed to the browser, which we consume here. + host().var_tracker().ReleaseVar(host_pp_var); + EXPECT_EQ(1, host().var_tracker().GetRefCountForObject(host_pp_var)); // The plugin is going away; generally, so will all references to its instance // object. - ReleaseVar(host_obj); + host().var_tracker().ReleaseVar(host_pp_var); // Destroy the instance. DidDestroy above decrements the reference count for // instance_obj, so it should also be destroyed. ppp_instance->DidDestroy(kInstance); - EXPECT_EQ(-1, plugin_var_tracker.GetRefCountForObject(instance_obj)); - // Check the host-side reference count. - EXPECT_EQ(0u, id_refcount_map.size()); + EXPECT_EQ(-1, plugin().var_tracker().GetRefCountForObject(instance_obj)); + EXPECT_EQ(-1, host().var_tracker().GetRefCountForObject(host_pp_var)); } } // namespace proxy diff --git a/ppapi/proxy/ppp_instance_proxy_unittest.cc b/ppapi/proxy/ppp_instance_proxy_unittest.cc index c97ef21..6e53023 100644 --- a/ppapi/proxy/ppp_instance_proxy_unittest.cc +++ b/ppapi/proxy/ppp_instance_proxy_unittest.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. @@ -12,6 +12,8 @@ #include "ppapi/c/private/ppb_flash_fullscreen.h" #include "ppapi/proxy/ppapi_messages.h" #include "ppapi/proxy/ppapi_proxy_test.h" +#include "ppapi/shared_impl/ppb_view_shared.h" +#include "ppapi/shared_impl/scoped_pp_resource.h" namespace ppapi { namespace proxy { @@ -114,10 +116,11 @@ TEST_F(PPP_Instance_ProxyTest, PPPInstance1_0) { host().RegisterTestInterface(PPB_FULLSCREEN_INTERFACE, &ppb_fullscreen); - // Grab the host-side proxy for the 1.0 interface. - const PPP_Instance_1_0* ppp_instance = static_cast<const PPP_Instance_1_0*>( + // Grab the host-side proxy for the interface. The browser only speaks 1.1, + // while the proxy ensures support for the 1.0 version on the plugin side. + const PPP_Instance_1_1* ppp_instance = static_cast<const PPP_Instance_1_1*>( host().host_dispatcher()->GetProxiedInterface( - PPP_INSTANCE_INTERFACE_1_0)); + PPP_INSTANCE_INTERFACE_1_1)); // Call each function in turn, make sure we get the expected values and // returns. @@ -140,6 +143,8 @@ TEST_F(PPP_Instance_ProxyTest, PPPInstance1_0) { uint32_t expected_argc = expected_argn.size(); bool_to_return = PP_TRUE; ResetReceived(); + // Tell the host resource tracker about the instance. + host().resource_tracker().DidCreateInstance(expected_instance); EXPECT_EQ(bool_to_return, ppp_instance->DidCreate(expected_instance, expected_argc, &argn_to_pass[0], @@ -151,9 +156,17 @@ TEST_F(PPP_Instance_ProxyTest, PPPInstance1_0) { PP_Rect expected_position = { {1, 2}, {3, 4} }; PP_Rect expected_clip = { {5, 6}, {7, 8} }; + ViewData data; + data.rect = expected_position; + data.is_fullscreen = false; + data.is_page_visible = true; + data.clip_rect = expected_clip; ResetReceived(); - ppp_instance->DidChangeView(expected_instance, &expected_position, - &expected_clip); + ScopedPPResource view_resource( + ScopedPPResource::PassRef(), + (new PPB_View_Shared(PPB_View_Shared::InitAsImpl(), + expected_instance, data))->GetReference()); + ppp_instance->DidChangeView(expected_instance, view_resource); did_change_view_called.Wait(); EXPECT_EQ(received_instance, expected_instance); EXPECT_EQ(received_position.point.x, expected_position.point.x); @@ -176,6 +189,8 @@ TEST_F(PPP_Instance_ProxyTest, PPPInstance1_0) { // HandleResourceLoad. It also requires // PPB_Core.AddRefResource and for PPB_URLLoader to be // registered. + + host().resource_tracker().DidDeleteInstance(expected_instance); } } // namespace proxy diff --git a/ppapi/proxy/ppp_messaging_proxy_unittest.cc b/ppapi/proxy/ppp_messaging_proxy_unittest.cc index ed12e57..8e46a4a 100644 --- a/ppapi/proxy/ppp_messaging_proxy_unittest.cc +++ b/ppapi/proxy/ppp_messaging_proxy_unittest.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. @@ -41,38 +41,15 @@ PPP_Messaging ppp_messaging_mock = { &HandleMessage }; -// Define a fake PPB_Var for the host side so that we can send a string var. -void AddRef(PP_Var /*var*/) { -} -void Release(PP_Var /*var*/) { -} -PP_Var VarFromUtf8(const char* /*data*/, uint32_t len) { - return PP_MakeUndefined(); -} -// No matter what id we're given, always provide kTestString and its length. -const std::string kTestString = "Hello world!"; -const char* VarToUtf8(PP_Var /*var*/, uint32_t* len) { - *len = kTestString.size(); - return kTestString.c_str(); -} - -PPB_Var ppb_var_mock = { - &AddRef, - &Release, - &VarFromUtf8, - &VarToUtf8 -}; - } // namespace class PPP_Messaging_ProxyTest : public TwoWayTest { public: - PPP_Messaging_ProxyTest() - : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) { - plugin().RegisterTestInterface(PPP_MESSAGING_INTERFACE, - &ppp_messaging_mock); - host().RegisterTestInterface(PPB_VAR_INTERFACE, &ppb_var_mock); - } + PPP_Messaging_ProxyTest() + : TwoWayTest(TwoWayTest::TEST_PPP_INTERFACE) { + plugin().RegisterTestInterface(PPP_MESSAGING_INTERFACE, + &ppp_messaging_mock); + } }; TEST_F(PPP_Messaging_ProxyTest, SendMessages) { @@ -120,17 +97,22 @@ TEST_F(PPP_Messaging_ProxyTest, SendMessages) { EXPECT_EQ(expected_var.type, received_var.type); EXPECT_EQ(expected_var.value.as_double, received_var.value.as_double); - expected_var.type = PP_VARTYPE_STRING; - expected_var.value.as_id = 1979; + const std::string kTestString("Hello world!"); + expected_var = StringVar::StringToPPVar(kTestString); ResetReceived(); ppp_messaging->HandleMessage(expected_instance, expected_var); + // Now release the var, and the string should go away (because the ref + // count should be one). + host().var_tracker().ReleaseVar(expected_var); + EXPECT_FALSE(StringVar::FromPPVar(expected_var)); + handle_message_called.Wait(); EXPECT_EQ(expected_instance, received_instance); EXPECT_EQ(expected_var.type, received_var.type); - - StringVar* received_string = StringVar::FromPPVar(received_var); + Var* received_string = plugin().var_tracker().GetVar(received_var); ASSERT_TRUE(received_string); - EXPECT_EQ(kTestString, received_string->value()); + ASSERT_TRUE(received_string->AsStringVar()); + EXPECT_EQ(kTestString, received_string->AsStringVar()->value()); // Now release the var, and the string should go away (because the ref // count should be one). plugin().var_tracker().ReleaseVar(received_var); diff --git a/ppapi/proxy/serialized_var_unittest.cc b/ppapi/proxy/serialized_var_unittest.cc index 150f5e7..494a68d 100644 --- a/ppapi/proxy/serialized_var_unittest.cc +++ b/ppapi/proxy/serialized_var_unittest.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. @@ -115,7 +115,8 @@ TEST_F(SerializedVarTest, PluginSerializedStringVarInOutParam) { EXPECT_EQ(0u, sink().message_count()); } -// Tests receiving an argument and passing it back out as an output parameter. +// Tests receiving an argument and passing it back to the browser as an output +// parameter. TEST_F(SerializedVarTest, PluginSerializedVarOutParam) { PP_Var host_object = MakeObjectVar(0x31337); diff --git a/ppapi/shared_impl/ppapi_globals.cc b/ppapi/shared_impl/ppapi_globals.cc index 9b5e9a8..0fab3dc 100644 --- a/ppapi/shared_impl/ppapi_globals.cc +++ b/ppapi/shared_impl/ppapi_globals.cc @@ -1,13 +1,24 @@ -// 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. #include "ppapi/shared_impl/ppapi_globals.h" +#include "base/lazy_instance.h" // For testing purposes only. #include "base/logging.h" +#include "base/threading/thread_local.h" // For testing purposes only. namespace ppapi { +namespace { +// Thread-local globals for testing. See SetPpapiGlobalsOnThreadForTest for more +// information. +base::LazyInstance< + base::ThreadLocalPointer<PpapiGlobals>, + base::LeakyLazyInstanceTraits<base::ThreadLocalPointer<PpapiGlobals> > > + tls_ppapi_globals_for_test = LAZY_INSTANCE_INITIALIZER; +} // namespace + PpapiGlobals* PpapiGlobals::ppapi_globals_ = NULL; PpapiGlobals::PpapiGlobals() { @@ -15,9 +26,34 @@ PpapiGlobals::PpapiGlobals() { ppapi_globals_ = this; } +PpapiGlobals::PpapiGlobals(ForTest) { + DCHECK(!ppapi_globals_); +} + PpapiGlobals::~PpapiGlobals() { - DCHECK(ppapi_globals_ == this); + DCHECK(ppapi_globals_ == this || !ppapi_globals_); ppapi_globals_ = NULL; } +// static +void PpapiGlobals::SetPpapiGlobalsOnThreadForTest(PpapiGlobals* ptr) { + // If we're using a per-thread PpapiGlobals, we should not have a global one. + // If we allowed it, it would always over-ride the "test" versions. + DCHECK(!ppapi_globals_); + tls_ppapi_globals_for_test.Pointer()->Set(ptr); +} + +bool PpapiGlobals::IsHostGlobals() const { + return false; +} + +bool PpapiGlobals::IsPluginGlobals() const { + return false; +} + +// static +PpapiGlobals* PpapiGlobals::GetThreadLocalPointer() { + return tls_ppapi_globals_for_test.Pointer()->Get(); +} + } // namespace ppapi diff --git a/ppapi/shared_impl/ppapi_globals.h b/ppapi/shared_impl/ppapi_globals.h index b3d7d55..737c3a2 100644 --- a/ppapi/shared_impl/ppapi_globals.h +++ b/ppapi/shared_impl/ppapi_globals.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. @@ -6,11 +6,16 @@ #define PPAPI_SHARED_IMPL_PPAPI_GLOBALS_H_ #include "base/basictypes.h" +#include "base/threading/thread_local.h" // For testing purposes only. #include "ppapi/c/pp_instance.h" #include "ppapi/c/pp_module.h" #include "ppapi/shared_impl/api_id.h" #include "ppapi/shared_impl/ppapi_shared_export.h" +namespace base { +class Lock; +} + namespace ppapi { class CallbackTracker; @@ -22,16 +27,42 @@ class VarTracker; class PPAPI_SHARED_EXPORT PpapiGlobals { public: PpapiGlobals(); + + // This constructor is to be used only for making a PpapiGlobal for testing + // purposes. This avoids setting the global static ppapi_globals_. For unit + // tests that use this feature, the "test" PpapiGlobals should be constructed + // using this method. See SetPpapiGlobalsOnThreadForTest for more information. + struct ForTest {}; + PpapiGlobals(ForTest); + virtual ~PpapiGlobals(); // Getter for the global singleton. - inline static PpapiGlobals* Get() { return ppapi_globals_; } + inline static PpapiGlobals* Get() { + if (ppapi_globals_) + return ppapi_globals_; + // In unit tests, the following might be valid (see + // SetPpapiGlobalsOnThreadForTest). Normally, this will just return NULL. + return GetThreadLocalPointer(); + } + + // This allows us to set a given PpapiGlobals object as the PpapiGlobals for + // a given thread. After setting the PpapiGlobals for a thread, Get() will + // return that PpapiGlobals when Get() is called on that thread. Other threads + // are unaffected. This allows us to have tests which use >1 PpapiGlobals in + // the same process, e.g. for having 1 thread emulate the "host" and 1 thread + // emulate the "plugin". + // + // PpapiGlobals object must have been constructed using the "ForTest" + // parameter. + static void SetPpapiGlobalsOnThreadForTest(PpapiGlobals* ptr); // Retrieves the corresponding tracker. virtual ResourceTracker* GetResourceTracker() = 0; virtual VarTracker* GetVarTracker() = 0; virtual CallbackTracker* GetCallbackTrackerForInstance( PP_Instance instance) = 0; + virtual base::Lock* GetProxyLock() = 0; // Returns the function object corresponding to the given ID, or NULL if // there isn't one. @@ -41,7 +72,15 @@ class PPAPI_SHARED_EXPORT PpapiGlobals { // failure. virtual PP_Module GetModuleForInstance(PP_Instance instance) = 0; + virtual bool IsHostGlobals() const; + virtual bool IsPluginGlobals() const; + private: + // Return the thread-local pointer which is used only for unit testing. It + // should always be NULL when running in production. It allows separate + // threads to have distinct "globals". + static PpapiGlobals* GetThreadLocalPointer(); + static PpapiGlobals* ppapi_globals_; DISALLOW_COPY_AND_ASSIGN(PpapiGlobals); diff --git a/ppapi/shared_impl/proxy_lock.cc b/ppapi/shared_impl/proxy_lock.cc index 3d84930..226c51f 100644 --- a/ppapi/shared_impl/proxy_lock.cc +++ b/ppapi/shared_impl/proxy_lock.cc @@ -1,35 +1,26 @@ -// 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. #include "ppapi/shared_impl/proxy_lock.h" #include "base/synchronization/lock.h" +#include "ppapi/shared_impl/ppapi_globals.h" namespace ppapi { -base::Lock* ProxyLock::lock_ = NULL; - // static void ProxyLock::Acquire() { - if (lock_) - lock_->Acquire(); + base::Lock* lock(PpapiGlobals::Get()->GetProxyLock()); + if (lock) + lock->Acquire(); } // static void ProxyLock::Release() { - if (lock_) - lock_->Release(); -} - -// static -void ProxyLock::Set(base::Lock* lock) { - lock_ = lock; -} - -// static -void ProxyLock::Reset() { - Set(NULL); + base::Lock* lock(PpapiGlobals::Get()->GetProxyLock()); + if (lock) + lock->Release(); } } // namespace ppapi diff --git a/ppapi/shared_impl/proxy_lock.h b/ppapi/shared_impl/proxy_lock.h index cc90501..c5571f3 100644 --- a/ppapi/shared_impl/proxy_lock.h +++ b/ppapi/shared_impl/proxy_lock.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. @@ -34,14 +34,6 @@ class PPAPI_SHARED_EXPORT ProxyLock { // Relinquish the proxy lock. If the lock has not been set, this does nothing. static void Release(); - // Set the lock that ProxyLock will use. The caller is responsible for - // ensuring that the lock stays valid so long as the ProxyLock may be in use. - static void Set(base::Lock* lock); - // Set the lock to NULL. - static void Reset(); - private: - static base::Lock* lock_; - DISALLOW_IMPLICIT_CONSTRUCTORS(ProxyLock); }; diff --git a/ppapi/shared_impl/test_globals.cc b/ppapi/shared_impl/test_globals.cc index e870e5c..f661998 100644 --- a/ppapi/shared_impl/test_globals.cc +++ b/ppapi/shared_impl/test_globals.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. @@ -11,6 +11,11 @@ TestGlobals::TestGlobals() callback_tracker_(new CallbackTracker) { } +TestGlobals::TestGlobals(PpapiGlobals::ForTest for_test) + : ppapi::PpapiGlobals(for_test), + callback_tracker_(new CallbackTracker) { +} + TestGlobals::~TestGlobals() { } @@ -35,4 +40,8 @@ PP_Module TestGlobals::GetModuleForInstance(PP_Instance instance) { return 0; } +base::Lock* TestGlobals::GetProxyLock() { + return NULL; +} + } // namespace ppapi diff --git a/ppapi/shared_impl/test_globals.h b/ppapi/shared_impl/test_globals.h index 9c58fd3..9af6664 100644 --- a/ppapi/shared_impl/test_globals.h +++ b/ppapi/shared_impl/test_globals.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. @@ -27,6 +27,7 @@ class TestVarTracker : public VarTracker { class TestGlobals : public PpapiGlobals { public: TestGlobals(); + TestGlobals(PpapiGlobals::ForTest); virtual ~TestGlobals(); // PpapiGlobals implementation. @@ -37,6 +38,7 @@ class TestGlobals : public PpapiGlobals { virtual FunctionGroupBase* GetFunctionAPI(PP_Instance inst, ApiID id) OVERRIDE; virtual PP_Module GetModuleForInstance(PP_Instance instance) OVERRIDE; + virtual base::Lock* GetProxyLock() OVERRIDE; private: ResourceTracker resource_tracker_; diff --git a/ppapi/shared_impl/var_tracker.cc b/ppapi/shared_impl/var_tracker.cc index 58c715c..0b70349 100644 --- a/ppapi/shared_impl/var_tracker.cc +++ b/ppapi/shared_impl/var_tracker.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. @@ -129,6 +129,21 @@ VarTracker::VarMap::iterator VarTracker::GetLiveVar(int32 id) { return live_vars_.find(id); } +int VarTracker::GetRefCountForObject(const PP_Var& plugin_object) { + VarMap::iterator found = GetLiveVar(plugin_object); + if (found == live_vars_.end()) + return -1; + return found->second.ref_count; +} + +int VarTracker::GetTrackedWithNoReferenceCountForObject( + const PP_Var& plugin_object) { + VarMap::iterator found = GetLiveVar(plugin_object); + if (found == live_vars_.end()) + return -1; + return found->second.track_with_no_reference_count; +} + VarTracker::VarMap::iterator VarTracker::GetLiveVar(const PP_Var& var) { return live_vars_.find(static_cast<int32>(var.value.as_id)); } diff --git a/ppapi/shared_impl/var_tracker.h b/ppapi/shared_impl/var_tracker.h index 4dc8a2d..52e38bd 100644 --- a/ppapi/shared_impl/var_tracker.h +++ b/ppapi/shared_impl/var_tracker.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. @@ -68,6 +68,12 @@ class PPAPI_SHARED_EXPORT VarTracker { // and their reference counts are unaffected. std::vector<PP_Var> GetLiveVars(); + // Retrieves the internal reference counts for testing. Returns 0 if we + // know about the object but the corresponding value is 0, or -1 if the + // given object ID isn't in our map. + int GetRefCountForObject(const PP_Var& object); + int GetTrackedWithNoReferenceCountForObject(const PP_Var& object); + protected: struct VarInfo { VarInfo(); diff --git a/webkit/plugins/ppapi/host_globals.cc b/webkit/plugins/ppapi/host_globals.cc index ab51983..7705dcc 100644 --- a/webkit/plugins/ppapi/host_globals.cc +++ b/webkit/plugins/ppapi/host_globals.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. @@ -45,8 +45,13 @@ HostGlobals::HostGlobals() : ::ppapi::PpapiGlobals() { host_globals_ = this; } +HostGlobals::HostGlobals(::ppapi::PpapiGlobals::ForTest for_test) + : ::ppapi::PpapiGlobals(for_test) { + DCHECK(!host_globals_); +} + HostGlobals::~HostGlobals() { - DCHECK(host_globals_ == this); + DCHECK(host_globals_ == this || !host_globals_); host_globals_ = NULL; } @@ -116,6 +121,11 @@ PP_Module HostGlobals::GetModuleForInstance(PP_Instance instance) { return inst->module()->pp_module(); } +base::Lock* HostGlobals::GetProxyLock() { + // We do not lock on the host side. + return NULL; +} + PP_Module HostGlobals::AddModule(PluginModule* module) { #ifndef NDEBUG // Make sure we're not adding one more than once. @@ -197,5 +207,9 @@ PluginInstance* HostGlobals::GetInstance(PP_Instance instance) { return found->second->instance; } +bool HostGlobals::IsHostGlobals() const { + return true; +} + } // namespace ppapi } // namespace webkit diff --git a/webkit/plugins/ppapi/host_globals.h b/webkit/plugins/ppapi/host_globals.h index db840aa..d0926bc 100644 --- a/webkit/plugins/ppapi/host_globals.h +++ b/webkit/plugins/ppapi/host_globals.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. @@ -22,12 +22,16 @@ class PluginModule; class HostGlobals : public ::ppapi::PpapiGlobals { public: HostGlobals(); + HostGlobals(::ppapi::PpapiGlobals::ForTest); virtual ~HostGlobals(); // Getter for the global singleton. Generally, you should use // PpapiGlobals::Get() when possible. Use this only when you need some // host-specific functionality. - inline static HostGlobals* Get() { return host_globals_; } + inline static HostGlobals* Get() { + DCHECK(PpapiGlobals::Get()->IsHostGlobals()); + return static_cast<HostGlobals*>(PpapiGlobals::Get()); + } // PpapiGlobals implementation. virtual ::ppapi::ResourceTracker* GetResourceTracker() OVERRIDE; @@ -38,6 +42,7 @@ class HostGlobals : public ::ppapi::PpapiGlobals { PP_Instance inst, ::ppapi::ApiID id) OVERRIDE; virtual PP_Module GetModuleForInstance(PP_Instance instance) OVERRIDE; + virtual base::Lock* GetProxyLock() OVERRIDE; HostVarTracker* host_var_tracker() { return &host_var_tracker_; @@ -75,6 +80,9 @@ class HostGlobals : public ::ppapi::PpapiGlobals { WEBKIT_PLUGINS_EXPORT PluginInstance* GetInstance(PP_Instance instance); private: + // PpapiGlobals overrides. + virtual bool IsHostGlobals() const OVERRIDE; + // Per-instance data we track. struct InstanceData; |