diff options
author | siggi@chromium.org <siggi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-15 15:14:55 +0000 |
---|---|---|
committer | siggi@chromium.org <siggi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-15 15:14:55 +0000 |
commit | 5d10081cdc1162f897d9301afadb4981206ba974 (patch) | |
tree | 4e3dd07d1ba61b8a0e8dd307026edbfc35aa7157 | |
parent | eb57bb21a94acdc46ab1496d103c2cb4739b158a (diff) | |
download | chromium_src-5d10081cdc1162f897d9301afadb4981206ba974.zip chromium_src-5d10081cdc1162f897d9301afadb4981206ba974.tar.gz chromium_src-5d10081cdc1162f897d9301afadb4981206ba974.tar.bz2 |
COM replaced with RPC for firing events in broker.
Sumbmitting for Vitaly Buka, see original change at http://codereview.chromium.org/4508002/.
BUG=none
TEST=Unittests in this change.
Review URL: http://codereview.chromium.org/5010001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66121 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | ceee/ie/broker/broker.cc | 13 | ||||
-rw-r--r-- | ceee/ie/broker/broker.gyp | 45 | ||||
-rw-r--r-- | ceee/ie/broker/broker.h | 8 | ||||
-rw-r--r-- | ceee/ie/broker/broker_module.cc | 6 | ||||
-rw-r--r-- | ceee/ie/broker/broker_rpc_client.cc | 116 | ||||
-rw-r--r-- | ceee/ie/broker/broker_rpc_client.h | 47 | ||||
-rw-r--r-- | ceee/ie/broker/broker_rpc_lib.idl | 35 | ||||
-rw-r--r-- | ceee/ie/broker/broker_rpc_server.cc | 130 | ||||
-rw-r--r-- | ceee/ie/broker/broker_rpc_server.h | 36 | ||||
-rw-r--r-- | ceee/ie/broker/broker_rpc_unittest.cc | 81 | ||||
-rw-r--r-- | ceee/ie/broker/broker_rpc_utils.cc | 37 | ||||
-rw-r--r-- | ceee/ie/broker/broker_rpc_utils.h | 19 | ||||
-rw-r--r-- | ceee/ie/broker/executors_manager.cc | 18 | ||||
-rw-r--r-- | ceee/ie/ie.gyp | 3 | ||||
-rw-r--r-- | ceee/ie/plugin/toolband/toolband.gyp | 2 | ||||
-rw-r--r-- | ceee/ie/plugin/toolband/toolband_module.cc | 49 |
16 files changed, 572 insertions, 73 deletions
diff --git a/ceee/ie/broker/broker.cc b/ceee/ie/broker/broker.cc index 24ed0da..3c3f8ce 100644 --- a/ceee/ie/broker/broker.cc +++ b/ceee/ie/broker/broker.cc @@ -21,19 +21,6 @@ HRESULT CeeeBroker::FinalConstruct() { return S_OK; } -void CeeeBroker::OnAddConnection(bool first_lock) { - if (first_lock) - ceee_module_util::LockModule(); -} - -void CeeeBroker::OnReleaseConnection(bool last_unlock, - bool last_unlock_releases) { - if (last_unlock) - ceee_module_util::UnlockModule(); - IExternalConnectionImpl<CeeeBroker>::OnReleaseConnection( - last_unlock, last_unlock_releases); -} - STDMETHODIMP CeeeBroker::Execute(BSTR function, BSTR* response) { // This is DEPRECATED and we should use ChromePostman (see FireEvent). api_dispatcher_->HandleApiRequest(function, response); diff --git a/ceee/ie/broker/broker.gyp b/ceee/ie/broker/broker.gyp index fbd2167f..1c01487 100644 --- a/ceee/ie/broker/broker.gyp +++ b/ceee/ie/broker/broker.gyp @@ -11,9 +11,46 @@ ], 'targets': [ { + 'target_name': 'broker_rpc_idl', + 'type': 'none', + 'sources': [ + 'broker_rpc_lib.idl', + ], + 'msvs_settings': { + 'VCMIDLTool': { + 'OutputDirectory': '<(SHARED_INTERMEDIATE_DIR)', + 'DLLDataFileName': '$(InputName)_dlldata.c', + 'AdditionalOptions': '/prefix all "BrokerRpcClient_" ' + 'server "BrokerRpcServer_"' + }, + }, + # Add the output dir for those who depend on us. + 'direct_dependent_settings': { + 'include_dirs': ['<(SHARED_INTERMEDIATE_DIR)'], + }, + }, + { + 'target_name': 'broker_rpc_lib', + 'type': 'static_library', + 'dependencies': [ + 'broker_rpc_idl', + ], + 'sources': [ + '<(SHARED_INTERMEDIATE_DIR)/broker_rpc_lib_c.c', + '<(SHARED_INTERMEDIATE_DIR)/broker_rpc_lib_s.c', + ], + 'msvs_settings': { + 'VCCLCompilerTool': { + 'UsePrecompiledHeader': '0', + 'ForcedIncludeFiles': '$(NOINHERIT)', + }, + }, + }, + { 'target_name': 'broker', 'type': 'static_library', 'dependencies': [ + 'broker_rpc_idl', '../common/common.gyp:ie_common', '../common/common.gyp:ie_common_settings', '../plugin/toolband/toolband.gyp:toolband_idl', @@ -34,6 +71,12 @@ 'broker.cc', 'broker.h', 'broker_docs.h', + 'broker_rpc_client.cc', + 'broker_rpc_client.h', + 'broker_rpc_server.cc', + 'broker_rpc_server.h', + 'broker_rpc_utils.cc', + 'broker_rpc_utils.h', 'chrome_postman.cc', 'chrome_postman.h', 'common_api_module.cc', @@ -85,6 +128,7 @@ ], 'dependencies': [ 'broker', + 'broker_rpc_lib', '../common/common.gyp:ie_common_settings', '../common/common.gyp:ie_guids', '../plugin/toolband/toolband.gyp:toolband_idl', @@ -109,6 +153,7 @@ 'libraries': [ 'oleacc.lib', 'iepmapi.lib', + 'rpcrt4.lib', ], }, ] diff --git a/ceee/ie/broker/broker.h b/ceee/ie/broker/broker.h index 8132e8a..f8e7ed8 100644 --- a/ceee/ie/broker/broker.h +++ b/ceee/ie/broker/broker.h @@ -27,14 +27,12 @@ class ATL_NO_VTABLE CeeeBroker : public CComObjectRootEx<CComMultiThreadModel>, public CComCoClass<CeeeBroker, &CLSID_CeeeBroker>, public ICeeeBroker, - public ICeeeBrokerRegistrar, - public IExternalConnectionImpl<CeeeBroker> { + public ICeeeBrokerRegistrar { public: DECLARE_REGISTRY_RESOURCEID(IDR_BROKER) DECLARE_NOT_AGGREGATABLE(CeeeBroker) BEGIN_COM_MAP(CeeeBroker) - COM_INTERFACE_ENTRY(IExternalConnection) COM_INTERFACE_ENTRY(ICeeeBrokerRegistrar) COM_INTERFACE_ENTRY(ICeeeBroker) END_COM_MAP() @@ -57,10 +55,6 @@ class ATL_NO_VTABLE CeeeBroker STDMETHOD(SetTabIdForHandle)(long tab_id, CeeeWindowHandle handle); // @} - // IExternalConnectionImpl overrides - void OnAddConnection(bool first_lock); - void OnReleaseConnection(bool last_unlock, bool last_unlock_releases); - protected: // A pointer to single instance objects, or seams set for unittests. ExecutorsManager * executors_manager_; diff --git a/ceee/ie/broker/broker_module.cc b/ceee/ie/broker/broker_module.cc index 38b8529..fca2164 100644 --- a/ceee/ie/broker/broker_module.cc +++ b/ceee/ie/broker/broker_module.cc @@ -13,6 +13,7 @@ #include "base/logging.h" #include "base/logging_win.h" #include "ceee/ie/broker/broker.h" +#include "ceee/ie/broker/broker_rpc_server.h" #include "ceee/ie/broker/chrome_postman.h" #include "ceee/ie/broker/executors_manager.h" #include "ceee/ie/broker/resource.h" @@ -79,6 +80,7 @@ class CeeeBrokerModule : public CAtlExeModuleT<CeeeBrokerModule> { CComObjectStackEx<ChromePostman> chrome_postman_; CrashReporter crash_reporter_; base::AtExitManager at_exit_; + BrokerRpcServer rpc_server_; }; CeeeBrokerModule module; @@ -158,6 +160,10 @@ HRESULT CeeeBrokerModule::PreMessageLoop(int show) { // API invocation or Fire events before the postman is ready to handle them. chrome_postman_.Init(); WindowEventsFunnel::Initialize(); + + if (!rpc_server_.Start()) + return RPC_E_FAULT; + return CAtlExeModuleT<CeeeBrokerModule>::PreMessageLoop(show); } diff --git a/ceee/ie/broker/broker_rpc_client.cc b/ceee/ie/broker/broker_rpc_client.cc new file mode 100644 index 0000000..38506d6 --- /dev/null +++ b/ceee/ie/broker/broker_rpc_client.cc @@ -0,0 +1,116 @@ +// Copyright (c) 2010 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. +// +// Broker RPC Client implementation. + +#include "ceee/ie/broker/broker_rpc_client.h" + +#include "base/lock.h" +#include "base/logging.h" +#include "broker_rpc_lib.h" // NOLINT +#include "ceee/common/com_utils.h" +#include "ceee/ie/broker/broker_rpc_utils.h" + +BrokerRpcClient::BrokerRpcClient() : context_(0), binding_handle_(NULL) { +} + +BrokerRpcClient::~BrokerRpcClient() { + Disconnect(); +} + +int HandleRpcException(unsigned int rpc_exception_code) { + switch (rpc_exception_code) { + case STATUS_ACCESS_VIOLATION: + case STATUS_DATATYPE_MISALIGNMENT: + case STATUS_PRIVILEGED_INSTRUCTION: + case STATUS_BREAKPOINT: + case STATUS_STACK_OVERFLOW: + case STATUS_IN_PAGE_ERROR: + case STATUS_GUARD_PAGE_VIOLATION: + return EXCEPTION_CONTINUE_SEARCH; + default: + break; + } + return EXCEPTION_EXECUTE_HANDLER; +} + +void BrokerRpcClient::LockContext() { + RpcTryExcept { + context_ = BrokerRpcClient_Connect(binding_handle_); + } RpcExcept(HandleRpcException(RpcExceptionCode())) { + LOG(ERROR) << "RPC error in LockContext: " << RpcExceptionCode(); + } RpcEndExcept +} + +void BrokerRpcClient::ReleaseContext() { + RpcTryExcept { + BrokerRpcClient_Disconnect(binding_handle_, &context_); + } RpcExcept(HandleRpcException(RpcExceptionCode())) { + LOG(ERROR) << "RPC error in ReleaseContext: " << RpcExceptionCode(); + } RpcEndExcept +} + +bool BrokerRpcClient::Connect() { + if (is_connected()) + return true; + + std::wstring end_point = GetRpcEndPointAddress(); + std::wstring protocol = kRpcProtocol; + DCHECK(!protocol.empty()); + DCHECK(!end_point.empty()); + if (protocol.empty() || end_point.empty()) + return false; + + // TODO(vitalybuka@google.com): There's no guarantee (aside from name + // uniqueness) that it will connect to an endpoint created by the same user. + // Hint: The missing invocation is RpcBindingSetAuthInfoEx. + LOG(INFO) << "Connecting to RPC server. Endpoint: " << end_point; + RPC_WSTR string_binding = NULL; + // Create binding string with given protocol and end point. + RPC_STATUS status = ::RpcStringBindingCompose( + NULL, + reinterpret_cast<RPC_WSTR>(&protocol[0]), + NULL, + reinterpret_cast<RPC_WSTR>(&end_point[0]), + NULL, + &string_binding); + LOG_IF(ERROR, RPC_S_OK != status) << + "Failed to compose binding string. RPC_STATUS=0x" << com::LogWe(status); + + if (RPC_S_OK == status) { + // Create binding from just generated binding string. Binding handle should + // used for PRC calls. + status = ::RpcBindingFromStringBinding(string_binding, &binding_handle_); + LOG_IF(ERROR, RPC_S_OK != status) << + "Failed to bind. RPC_STATUS=0x" << com::LogWe(status); + ::RpcStringFree(&string_binding); + if (RPC_S_OK == status) { + LOG(INFO) << "RPC client is connected. Endpoint: " << end_point; + LockContext(); + } + } + if (!is_connected()) + Disconnect(); + return is_connected(); +} + +void BrokerRpcClient::Disconnect() { + if (context_ != NULL) + ReleaseContext(); + if (binding_handle_ != NULL) { + RPC_STATUS status = ::RpcBindingFree(&binding_handle_); + LOG_IF(WARNING, RPC_S_OK != status) << + "Failed to unbind. RPC_STATUS=0x" << com::LogWe(status); + } +} + +bool BrokerRpcClient::FireEvent(BSTR event_name, BSTR event_args) { + RpcTryExcept { + BrokerRpcClient_FireEvent(binding_handle_, event_name, event_args); + return true; + } RpcExcept(HandleRpcException(RpcExceptionCode())) { + LOG(ERROR) << "RPC error in FireEvent: " << RpcExceptionCode(); + } RpcEndExcept + return false; +} diff --git a/ceee/ie/broker/broker_rpc_client.h b/ceee/ie/broker/broker_rpc_client.h new file mode 100644 index 0000000..c90496e --- /dev/null +++ b/ceee/ie/broker/broker_rpc_client.h @@ -0,0 +1,47 @@ +// Copyright (c) 2010 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. +// +// Broker RPC Client. + +#ifndef CEEE_IE_BROKER_BROKER_RPC_CLIENT_H_ +#define CEEE_IE_BROKER_BROKER_RPC_CLIENT_H_ + +#include <wtypes.h> +#include "base/basictypes.h" + +// Class provides comunication with BrokerRpcServer. +class BrokerRpcClient { + public: + BrokerRpcClient(); + ~BrokerRpcClient(); + + // Initialize connection with server. + bool Connect(); + + // Relese connection with server + void Disconnect(); + + // Returns true if object ready for remote calls. + bool is_connected() const { + return context_ != NULL && binding_handle_ != NULL; + } + + // @name Remote calls. + // @{ + // Calls FireEvent on server side. + bool FireEvent(BSTR event_name, BSTR event_args); + // @} + + private: + void LockContext(); + void ReleaseContext(); + + RPC_BINDING_HANDLE binding_handle_; + // Context handle. It is required to make RPC server know number of active + // clients. + void* context_; + DISALLOW_COPY_AND_ASSIGN(BrokerRpcClient); +}; + +#endif // CEEE_IE_BROKER_BROKER_RPC_CLIENT_H_ diff --git a/ceee/ie/broker/broker_rpc_lib.idl b/ceee/ie/broker/broker_rpc_lib.idl new file mode 100644 index 0000000..e1afe66 --- /dev/null +++ b/ceee/ie/broker/broker_rpc_lib.idl @@ -0,0 +1,35 @@ +import "oaidl.idl"; +import "ocidl.idl"; + + +[ uuid (931C5D3F-A6D7-411B-98ED-789FC9291302), + // TODO(vitalybuka@google.com): decide if we need meaningful version. + version(1.1), + pointer_default(unique), +] +interface CeeeBroker { + +// Context handle to allow server maintain number of active clients. +typedef [context_handle] void* BrokerContextHandle; + +// @name Implementation specific calls. +// @{ +// Returns context handle for new client. +BrokerContextHandle Connect( + [in] handle_t binding_handle); + +// Release context handle. +void Disconnect( + [in] handle_t binding_handle, + [in, out] BrokerContextHandle* context); +// @} + +// @name Remote calls. +// @{ +// Fires event to broker. +void FireEvent( + [in] handle_t binding_handle, + [in] BSTR event_name, + [in] BSTR event_args); +// @} +} diff --git a/ceee/ie/broker/broker_rpc_server.cc b/ceee/ie/broker/broker_rpc_server.cc new file mode 100644 index 0000000..b4286c4 --- /dev/null +++ b/ceee/ie/broker/broker_rpc_server.cc @@ -0,0 +1,130 @@ +// Copyright (c) 2010 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. +// +// Broker RPC Server implementation. + +#include "ceee/ie/broker/broker_rpc_server.h" + +#include "base/atomic_sequence_num.h" +#include "base/logging.h" +#include "base/win_util.h" +#include "broker_rpc_lib.h" // NOLINT +#include "ceee/common/com_utils.h" +#include "ceee/ie/broker/broker_module_util.h" +#include "ceee/ie/broker/broker_rpc_utils.h" +#include "ceee/ie/broker/chrome_postman.h" + +BrokerRpcServer::BrokerRpcServer() + : is_started_(false), + current_thread_(::GetCurrentThreadId()) { +} + +BrokerRpcServer::~BrokerRpcServer() { + DCHECK(current_thread_ == ::GetCurrentThreadId()); + Stop(); +} + +bool BrokerRpcServer::Start() { + DCHECK(current_thread_ == ::GetCurrentThreadId()); + + if (is_started()) + return true; + + std::wstring end_point = GetRpcEndPointAddress(); + std::wstring protocol = kRpcProtocol; + DCHECK(!protocol.empty()); + DCHECK(!end_point.empty()); + if (protocol.empty() || end_point.empty()) + return false; + + LOG(INFO) << "RPC server is starting. Endpoint: " << end_point; + // Tell RPC runtime to use local interprocess communication for given + // end point. + RPC_STATUS status = ::RpcServerUseProtseqEp( + reinterpret_cast<RPC_WSTR>(&protocol[0]), + RPC_C_PROTSEQ_MAX_REQS_DEFAULT, + reinterpret_cast<RPC_WSTR>(&end_point[0]), + NULL); + LOG_IF(ERROR, RPC_S_OK != status && RPC_S_DUPLICATE_ENDPOINT != status) << + "Failed to set protocol for RPC end point. RPC_STATUS=0x" << + com::LogWe(status); + if (RPC_S_OK == status || RPC_S_DUPLICATE_ENDPOINT == status) { + // Register RPC interface with the RPC runtime. + status = ::RpcServerRegisterIfEx(BrokerRpcServer_CeeeBroker_v1_1_s_ifspec, + NULL, NULL, 0, RPC_C_LISTEN_MAX_CALLS_DEFAULT, NULL); + LOG_IF(ERROR, RPC_S_OK != status) << + "Failed to register RPC interface. RPC_STATUS=0x" << com::LogWe(status); + if (RPC_S_OK == status) { + // Start listen for RPC calls. + status = ::RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); + LOG_IF(ERROR, RPC_S_OK != status) << + "Failed to start listening. RPC_STATUS=0x" << com::LogWe(status); + if (RPC_S_OK == status) { + LOG(INFO) << "RPC server is started. Endpoint: " << end_point; + is_started_ = true; + } + } + } + if (!is_started()) + Stop(); + + return is_started(); +} + +bool BrokerRpcServer::Stop() { + DCHECK(current_thread_ == ::GetCurrentThreadId()); + is_started_ = false; + // Stop server listening for RPC. + RPC_STATUS status = ::RpcMgmtStopServerListening(NULL); + LOG_IF(WARNING, RPC_S_OK != status) << + "Failed to stop listening. RPC_STATUS=0x" << com::LogWe(status); + // Wait while server stops listening threads. + status = ::RpcMgmtWaitServerListen(); + LOG_IF(WARNING, RPC_S_OK != status) << + "Failed to wait server listen. RPC_STATUS=0x" << com::LogWe(status); + // Unregister RPC interface. + status = ::RpcServerUnregisterIf( + BrokerRpcServer_CeeeBroker_v1_1_s_ifspec, NULL, FALSE); + LOG_IF(WARNING, RPC_S_OK != status) << + "Failed to unregister interface. RPC_STATUS=0x" << com::LogWe(status); + return RPC_S_OK == status; +} + +bool BrokerRpcServer::is_started() const { + DCHECK(current_thread_ == ::GetCurrentThreadId()); + return is_started_; +} + +static base::AtomicSequenceNumber current_broker_rpc_context( + base::LINKER_INITIALIZED); + +BrokerContextHandle BrokerRpcServer_Connect(handle_t binding_handle) { + // TODO(vitalybuka@google.com): Add client identity check. + ceee_module_util::LockModule(); + return reinterpret_cast<void*>(current_broker_rpc_context.GetNext() + 1); +} + +void BrokerRpcServer_Disconnect( + handle_t binding_handle, + BrokerContextHandle* context) { + DCHECK(context != NULL); + if (context) + *context = NULL; + ceee_module_util::UnlockModule(); +} + +// Called when client process terminated without releasing context handle. +void __RPC_USER BrokerContextHandle_rundown(BrokerContextHandle context) { + DCHECK(context != NULL); + ceee_module_util::UnlockModule(); +} + +void BrokerRpcServer_FireEvent( + handle_t binding_handle, + BSTR event_name, + BSTR event_args) { + DCHECK(ChromePostman::GetInstance()); + if (ChromePostman::GetInstance()) + ChromePostman::GetInstance()->FireEvent(event_name, event_args); +} diff --git a/ceee/ie/broker/broker_rpc_server.h b/ceee/ie/broker/broker_rpc_server.h new file mode 100644 index 0000000..6c1698e --- /dev/null +++ b/ceee/ie/broker/broker_rpc_server.h @@ -0,0 +1,36 @@ +// Copyright (c) 2010 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. +// +// Broker RPC Server. + +#ifndef CEEE_IE_BROKER_BROKER_RPC_SERVER_H_ +#define CEEE_IE_BROKER_BROKER_RPC_SERVER_H_ + +#include <wtypes.h> +#include "base/basictypes.h" + +// Serving requests from BrokerRpcClient. +class BrokerRpcServer { + public: + BrokerRpcServer(); + ~BrokerRpcServer(); + + // Registers RPC interface and starts listening for requests. + bool Start(); + + // Unregister RPC interface. + bool Stop(); + + // Returns true if object is listening. + bool is_started() const; + + private: + // State of object. + bool is_started_; + DWORD current_thread_; + + DISALLOW_COPY_AND_ASSIGN(BrokerRpcServer); +}; + +#endif // CEEE_IE_BROKER_BROKER_RPC_SERVER_H_ diff --git a/ceee/ie/broker/broker_rpc_unittest.cc b/ceee/ie/broker/broker_rpc_unittest.cc new file mode 100644 index 0000000..44fc42e --- /dev/null +++ b/ceee/ie/broker/broker_rpc_unittest.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2010 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 "ceee/ie/broker/broker_rpc_client.h" +#include "ceee/ie/broker/broker_rpc_server.h" + +#include <atlbase.h> +#include "broker_rpc_lib.h" // NOLINT +#include "ceee/ie/broker/broker_rpc_utils.h" +#include "ceee/ie/common/ceee_module_util.h" +#include "ceee/testing/utils/mock_static.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::_; +using testing::StrEq; +using testing::StrictMock; +using testing::Return; + +namespace { + +using testing::_; + +MOCK_STATIC_CLASS_BEGIN(BrokerRpcMock) + MOCK_STATIC_INIT_BEGIN(BrokerRpcMock) + MOCK_STATIC_INIT(GetRpcEndPointAddress); + MOCK_STATIC_INIT(BrokerRpcServer_FireEvent) + MOCK_STATIC_INIT_END() + MOCK_STATIC0(std::wstring, , GetRpcEndPointAddress); + MOCK_STATIC3(void, , BrokerRpcServer_FireEvent, handle_t, BSTR, BSTR); +MOCK_STATIC_CLASS_END(BrokerRpcMock) + +class BrokerRpcTest : public testing::Test { + protected: + virtual void SetUp() { + EXPECT_CALL(broker_rpc_mock_, GetRpcEndPointAddress()) + .WillRepeatedly(Return(L"BrokerRpcTestEP")); + } + + virtual void TearDown() { + } + + BrokerRpcMock broker_rpc_mock_; +}; + +TEST_F(BrokerRpcTest, ConnectNoServer) { + BrokerRpcClient client; + ASSERT_FALSE(client.is_connected()); + ASSERT_FALSE(client.Connect()); + ASSERT_FALSE(client.is_connected()); +} + +TEST_F(BrokerRpcTest, Connect) { + BrokerRpcServer server; + ASSERT_FALSE(server.is_started()); + ASSERT_TRUE(server.Start()); + ASSERT_TRUE(server.is_started()); + BrokerRpcClient client; + ASSERT_TRUE(client.Connect()); + ASSERT_TRUE(client.is_connected()); +} + +TEST_F(BrokerRpcTest, FireEvent) { + BrokerRpcServer server; + ASSERT_TRUE(server.Start()); + + BrokerRpcClient client; + ASSERT_TRUE(client.Connect()); + + CComBSTR event_name = L"event_name"; + CComBSTR event_args = L"event_args"; + + EXPECT_CALL(broker_rpc_mock_, BrokerRpcServer_FireEvent(_, + StrEq(event_name.m_str), StrEq(event_args.m_str))) + .Times(1); + + ASSERT_TRUE(client.FireEvent(event_name, event_args)); +} + +} // namespace diff --git a/ceee/ie/broker/broker_rpc_utils.cc b/ceee/ie/broker/broker_rpc_utils.cc new file mode 100644 index 0000000..ad93c64 --- /dev/null +++ b/ceee/ie/broker/broker_rpc_utils.cc @@ -0,0 +1,37 @@ +// Copyright (c) 2010 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. +// +// Utilities shared by both Broker RPC client and server. + +#include "ceee/ie/broker/broker_rpc_utils.h" + +#include "base/win_util.h" +#include "ceee/common/process_utils_win.h" + +// Local interprocess communication only. +const wchar_t kRpcProtocol[] = L"ncalrpc"; + +std::wstring GetRpcEndPointAddress() { + std::wstring end_point; + bool running_as_admin = false; + // CEEE running as regular user and CEEE running as elevated user will start + // different broker processes. So make end points names different to connect + // to appropriate one. + process_utils_win::IsCurrentProcessUacElevated(&running_as_admin); + if (running_as_admin) + end_point += L"ADMIN-"; + std::wstring sid; + win_util::GetUserSidString(&sid); + end_point += sid; + end_point += L"-B4630D08-4621-41A1-A8D0-F1E98DA460D6"; + return end_point; +} + +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return malloc(len); +} + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); +} diff --git a/ceee/ie/broker/broker_rpc_utils.h b/ceee/ie/broker/broker_rpc_utils.h new file mode 100644 index 0000000..c6ea083 --- /dev/null +++ b/ceee/ie/broker/broker_rpc_utils.h @@ -0,0 +1,19 @@ +// Copyright (c) 2010 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. +// +// Utilities shared by both Broker RPC client and server. + +#ifndef CEEE_IE_BROKER_BROKER_RPC_UTILS_H_ +#define CEEE_IE_BROKER_BROKER_RPC_UTILS_H_ + +#include <string> + +// Protocol used for RPC comunication. +extern const wchar_t kRpcProtocol[]; + +// Returns RPC end point. Depends on current session ID and +// account used by chrome frame. +std::wstring GetRpcEndPointAddress(); + +#endif // CEEE_IE_BROKER_BROKER_RPC_UTILS_H_ diff --git a/ceee/ie/broker/executors_manager.cc b/ceee/ie/broker/executors_manager.cc index 5d87467..69f5b6f 100644 --- a/ceee/ie/broker/executors_manager.cc +++ b/ceee/ie/broker/executors_manager.cc @@ -87,11 +87,6 @@ HRESULT ExecutorsManager::RegisterTabExecutor(ThreadId thread_id, new_executor_info.thread_handle = thread_handle; } // End of lock. - if (map_was_empty) { - // We go from empty to not empty, - // so lock the module to make sure we stay alive. - ceee_module_util::LockModule(); - } return S_OK; } @@ -147,13 +142,6 @@ HRESULT ExecutorsManager::RegisterWindowExecutor(ThreadId thread_id, new_executor_info.thread_handle = thread_handle; } // End of lock. - if (map_was_empty) { - // We go from empty to not empty, - // so lock the module to make sure we stay alive. - ceee_module_util::LockModule(); - } - - // Update the list of handles that our thread is waiting on. BOOL success = ::SetEvent(update_threads_list_gate_); DCHECK(success); return S_OK; @@ -266,11 +254,6 @@ HRESULT ExecutorsManager::RemoveExecutor(ThreadId thread_id) { map_is_empty = executors_.empty(); } // End of lock. - if (map_is_empty) { - // We go from not empty to empty, - // so unlock the module it can leave in peace. - ceee_module_util::UnlockModule(); - } return S_OK; } @@ -285,7 +268,6 @@ HRESULT ExecutorsManager::Terminate() { if (!executors_.empty()) { // TODO(mad@chromium.org): Can this happen??? NOTREACHED(); - ceee_module_util::UnlockModule(); } executors_.clear(); diff --git a/ceee/ie/ie.gyp b/ceee/ie/ie.gyp index e2ea88e..5d11ded 100644 --- a/ceee/ie/ie.gyp +++ b/ceee/ie/ie.gyp @@ -29,6 +29,7 @@ 'broker/tab_api_module_unittest.cc', 'broker/window_api_module_unittest.cc', 'broker/window_events_funnel_unittest.cc', + 'broker/broker_rpc_unittest.cc', 'common/chrome_frame_host_unittest.cc', 'common/crash_reporter_unittest.cc', 'common/extension_manifest_unittest.cc', @@ -82,6 +83,7 @@ 'common/common.gyp:ie_common_settings', 'common/common.gyp:ie_guids', 'broker/broker.gyp:broker', + 'broker/broker.gyp:broker_rpc_lib', 'plugin/bho/bho.gyp:bho', 'plugin/scripting/scripting.gyp:javascript_bindings', 'plugin/scripting/scripting.gyp:scripting', @@ -98,6 +100,7 @@ 'libraries': [ 'oleacc.lib', 'iepmapi.lib', + 'rpcrt4.lib', ], }, { diff --git a/ceee/ie/plugin/toolband/toolband.gyp b/ceee/ie/plugin/toolband/toolband.gyp index 7019c85..6d2b50f 100644 --- a/ceee/ie/plugin/toolband/toolband.gyp +++ b/ceee/ie/plugin/toolband/toolband.gyp @@ -44,6 +44,7 @@ 'target_name': 'ceee_ie', 'type': 'shared_library', 'dependencies': [ + '../../broker/broker.gyp:broker_rpc_lib', 'ceee_ie_lib', 'ie_toolband_common', 'toolband_idl', @@ -72,6 +73,7 @@ 'libraries': [ 'oleacc.lib', 'iepmapi.lib', + 'rpcrt4.lib', ], 'include_dirs': [ # Allows us to include .tlb and .h files generated diff --git a/ceee/ie/plugin/toolband/toolband_module.cc b/ceee/ie/plugin/toolband/toolband_module.cc index 2d2c735..6cff4ba 100644 --- a/ceee/ie/plugin/toolband/toolband_module.cc +++ b/ceee/ie/plugin/toolband/toolband_module.cc @@ -12,6 +12,7 @@ #include "base/thread.h" #include "ceee/common/com_utils.h" #include "ceee/common/install_utils.h" +#include "ceee/ie/broker/broker_rpc_client.h" #include "ceee/ie/common/ceee_module_util.h" #include "ceee/ie/plugin/bho/browser_helper_object.h" #include "ceee/ie/plugin/bho/executor.h" @@ -66,6 +67,7 @@ class ToolbandModule : public CAtlDllModuleT<ToolbandModule> { const std::string& event_args); private: + // TODO(vitalybuka@google.com): Fire events without this thread. class ComWorkerThread : public base::Thread { public: ComWorkerThread(); @@ -80,10 +82,7 @@ class ToolbandModule : public CAtlDllModuleT<ToolbandModule> { // worker thread can be used. void FireEventToBroker(BSTR event_name, BSTR event_args); protected: - CComPtr<ICeeeBroker> broker_; - static const int kMaxNumberOfRetries = 5; - static const int64 kRetryDelayMs = 10; - int current_number_of_retries_; + BrokerRpcClient broker_rpc_; }; class FireEventTask : public Task { @@ -95,13 +94,6 @@ class ToolbandModule : public CAtlDllModuleT<ToolbandModule> { event_name_(event_name.c_str()), event_args_(event_args.c_str()) { } - FireEventTask(ComWorkerThread* worker_thread, - const BSTR event_name, - const BSTR event_args) - : worker_thread_(worker_thread), - event_name_(event_name), - event_args_(event_args) { - } virtual void Run() { worker_thread_->FireEventToBroker(event_name_, event_args_); } @@ -291,42 +283,29 @@ void ToolbandModule::FireEventToBroker(const std::string& event_name, ToolbandModule::ComWorkerThread::ComWorkerThread() - : base::Thread("CEEE-COM Worker Thread"), - current_number_of_retries_(0) { + : base::Thread("CEEE-COM Worker Thread") { } void ToolbandModule::ComWorkerThread::Init() { ::CoInitializeEx(0, COINIT_MULTITHREADED); + // TODO(vitalybuka@google.com): Start broker without COM. + CComPtr<ICeeeBroker> broker_; HRESULT hr = broker_.CoCreateInstance(CLSID_CeeeBroker); DCHECK(SUCCEEDED(hr)) << "Failed to create broker. " << com::LogHr(hr); + broker_rpc_.Connect(); + DCHECK(broker_rpc_.is_connected()); + ::CoUninitialize(); } void ToolbandModule::ComWorkerThread::CleanUp() { - broker_.Release(); - ::CoUninitialize(); + broker_rpc_.Disconnect(); } void ToolbandModule::ComWorkerThread::FireEventToBroker(BSTR event_name, - BSTR event_args) { - DCHECK(broker_ != NULL); - if (broker_ != NULL) { - HRESULT hr = broker_->FireEvent(event_name, event_args); - if (SUCCEEDED(hr)) { - current_number_of_retries_ = 0; - return; - } - // If the server is busy (which can happen if it is calling in as we try to - // to call out to it), then we should retry a few times a little later. - if (current_number_of_retries_ < kMaxNumberOfRetries && message_loop()) { - ++current_number_of_retries_; - LOG(WARNING) << "Retrying Broker FireEvent Failure. " << com::LogHr(hr); - message_loop()->PostDelayedTask(FROM_HERE, - new FireEventTask(this, event_name, event_args), kRetryDelayMs); - } else { - current_number_of_retries_ = 0; - DCHECK(SUCCEEDED(hr)) << "Broker FireEvent Failed. " << com::LogHr(hr); - } - } + BSTR event_args) { + DCHECK(broker_rpc_.is_connected()); + bool result = broker_rpc_.FireEvent(event_name, event_args); + DCHECK(result); } ToolbandModule module; |