summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsiggi@chromium.org <siggi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-15 15:14:55 +0000
committersiggi@chromium.org <siggi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-15 15:14:55 +0000
commit5d10081cdc1162f897d9301afadb4981206ba974 (patch)
tree4e3dd07d1ba61b8a0e8dd307026edbfc35aa7157
parenteb57bb21a94acdc46ab1496d103c2cb4739b158a (diff)
downloadchromium_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.cc13
-rw-r--r--ceee/ie/broker/broker.gyp45
-rw-r--r--ceee/ie/broker/broker.h8
-rw-r--r--ceee/ie/broker/broker_module.cc6
-rw-r--r--ceee/ie/broker/broker_rpc_client.cc116
-rw-r--r--ceee/ie/broker/broker_rpc_client.h47
-rw-r--r--ceee/ie/broker/broker_rpc_lib.idl35
-rw-r--r--ceee/ie/broker/broker_rpc_server.cc130
-rw-r--r--ceee/ie/broker/broker_rpc_server.h36
-rw-r--r--ceee/ie/broker/broker_rpc_unittest.cc81
-rw-r--r--ceee/ie/broker/broker_rpc_utils.cc37
-rw-r--r--ceee/ie/broker/broker_rpc_utils.h19
-rw-r--r--ceee/ie/broker/executors_manager.cc18
-rw-r--r--ceee/ie/ie.gyp3
-rw-r--r--ceee/ie/plugin/toolband/toolband.gyp2
-rw-r--r--ceee/ie/plugin/toolband/toolband_module.cc49
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;