| Index: ceee/ie/plugin/toolband/toolband_module.cc
|
| ===================================================================
|
| --- ceee/ie/plugin/toolband/toolband_module.cc (revision 66617)
|
| +++ ceee/ie/plugin/toolband/toolband_module.cc (working copy)
|
| @@ -9,10 +9,8 @@
|
| #include "base/command_line.h"
|
| #include "base/logging.h"
|
| #include "base/logging_win.h"
|
| -#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"
|
| @@ -61,76 +59,16 @@
|
| return module_initialized_;
|
| }
|
|
|
| - // Fires an event to the broker, so that the call can be made with an
|
| - // instance of a broker proxy that was CoCreated in the worker thread.
|
| - void FireEventToBroker(const std::string& event_name,
|
| - const std::string& event_args);
|
| -
|
| private:
|
| - // TODO(vitalybuka@google.com): Fire events without this thread.
|
| - class ComWorkerThread : public base::Thread {
|
| - public:
|
| - ComWorkerThread();
|
|
|
| - // Called just prior to starting the message loop
|
| - virtual void Init();
|
| -
|
| - // Called just after the message loop ends
|
| - virtual void CleanUp();
|
| -
|
| - // Called by FireEventTask so that the broker we instantiate in the
|
| - // worker thread can be used.
|
| - void FireEventToBroker(BSTR event_name, BSTR event_args);
|
| - protected:
|
| - BrokerRpcClient broker_rpc_;
|
| - };
|
| -
|
| - class FireEventTask : public Task {
|
| - public:
|
| - FireEventTask(ComWorkerThread* worker_thread,
|
| - const std::string& event_name,
|
| - const std::string& event_args)
|
| - : worker_thread_(worker_thread),
|
| - event_name_(event_name.c_str()),
|
| - event_args_(event_args.c_str()) {
|
| - }
|
| - virtual void Run() {
|
| - worker_thread_->FireEventToBroker(event_name_, event_args_);
|
| - }
|
| - private:
|
| - ComWorkerThread* worker_thread_;
|
| - CComBSTR event_name_;
|
| - CComBSTR event_args_;
|
| - };
|
| - // We only start the thread on first use. If we would start it on
|
| - // initialization, when our DLL is loaded into the broker process,
|
| - // it would try to start this thread which tries to CoCreate a Broker
|
| - // and this could cause a complex deadlock...
|
| - void EnsureThreadStarted();
|
| -
|
| - // We use a pointer so that we can make sure we only destroy the object
|
| - // when the thread is properly stopped. Otherwise, we would get a DCHECK
|
| - // if the thread is killed before we get to Stop it when DllCanUnloadNow
|
| - // returns S_OK, which happens when the application quits with live objects,
|
| - // this causes the destructor to DCHECK.
|
| - ComWorkerThread* worker_thread_;
|
| base::AtExitManager at_exit_;
|
| bool module_initialized_;
|
| bool crash_reporting_initialized_;
|
| -
|
| - int worker_thread_ref_count_;
|
| -
|
| - friend void ceee_module_util::AddRefModuleWorkerThread();
|
| - friend void ceee_module_util::ReleaseModuleWorkerThread();
|
| -
|
| - void IncThreadRefCount();
|
| - void DecThreadRefCount();
|
| };
|
|
|
| ToolbandModule::ToolbandModule()
|
| : crash_reporting_initialized_(false),
|
| - module_initialized_(false),
|
| - worker_thread_(NULL) {
|
| + module_initialized_(false) {
|
| wchar_t logfile_path[MAX_PATH];
|
| DWORD len = ::GetTempPath(arraysize(logfile_path), logfile_path);
|
| ::PathAppend(logfile_path, kLogFileName);
|
| @@ -162,10 +100,6 @@
|
| ToolbandModule::~ToolbandModule() {
|
| ScriptHost::set_default_debug_application(NULL);
|
|
|
| - // Just leave thread as is. Releasing interface from this thread may hang IE.
|
| - DCHECK(worker_thread_ref_count_ == 0);
|
| - DCHECK(worker_thread_ == NULL);
|
| -
|
| // Uninitialize control hosting.
|
| BOOL uninitialized = AtlAxWinTerm();
|
| DCHECK(uninitialized);
|
| @@ -175,43 +109,33 @@
|
|
|
| HRESULT ToolbandModule::DllCanUnloadNow() {
|
| HRESULT hr = CAtlDllModuleT<ToolbandModule>::DllCanUnloadNow();
|
| - if (hr == S_OK) {
|
| - // We must protect our data member against concurrent calls to check if we
|
| - // can be unloaded. We must also making the call to Term within the lock
|
| - // to make sure we don't try to re-initialize in case a new
|
| - // DllGetClassObject would occur in the mean time, in another thread.
|
| - m_csStaticDataInitAndTypeInfo.Lock();
|
| - if (module_initialized_) {
|
| - Term();
|
| - }
|
| - m_csStaticDataInitAndTypeInfo.Unlock();
|
| - }
|
| + if (hr == S_OK)
|
| + Term();
|
| return hr;
|
| }
|
|
|
| HRESULT ToolbandModule::DllGetClassObject(REFCLSID clsid, REFIID iid,
|
| void** object) {
|
| - // Same comment as above in ToolbandModule::DllCanUnloadNow().
|
| - m_csStaticDataInitAndTypeInfo.Lock();
|
| - if (!module_initialized_) {
|
| - Init();
|
| - }
|
| - m_csStaticDataInitAndTypeInfo.Unlock();
|
| + Init();
|
| return CAtlDllModuleT<ToolbandModule>::DllGetClassObject(clsid, iid, object);
|
| }
|
|
|
| void ToolbandModule::Init() {
|
| + // We must protect our data member against concurrent calls to check if we
|
| + // can be unloaded. We must also making the call to Term within the lock
|
| + // to make sure we don't try to re-initialize in case a new
|
| + // DllGetClassObject would occur in the mean time, in another thread.
|
| + CComCritSecLock<CComCriticalSection> lock(m_csStaticDataInitAndTypeInfo);
|
| + if (module_initialized_)
|
| + return;
|
| crash_reporting_initialized_ = InitializeCrashReporting();
|
| module_initialized_ = true;
|
| }
|
|
|
| void ToolbandModule::Term() {
|
| - if (worker_thread_ != NULL) {
|
| - // It is OK to call Stop on a thread even when it isn't running.
|
| - worker_thread_->Stop();
|
| - delete worker_thread_;
|
| - worker_thread_ = NULL;
|
| - }
|
| + CComCritSecLock<CComCriticalSection> lock(m_csStaticDataInitAndTypeInfo);
|
| + if (!module_initialized_)
|
| + return;
|
| if (crash_reporting_initialized_) {
|
| bool crash_reporting_deinitialized = ShutdownCrashReporting();
|
| DCHECK(crash_reporting_deinitialized);
|
| @@ -220,108 +144,8 @@
|
| module_initialized_ = false;
|
| }
|
|
|
| -void ToolbandModule::IncThreadRefCount() {
|
| - m_csStaticDataInitAndTypeInfo.Lock();
|
| - DCHECK_GE(worker_thread_ref_count_, 0);
|
| - worker_thread_ref_count_++;
|
| - m_csStaticDataInitAndTypeInfo.Unlock();
|
| -}
|
| -
|
| -void ToolbandModule::DecThreadRefCount() {
|
| - ComWorkerThread* thread = NULL;
|
| -
|
| - m_csStaticDataInitAndTypeInfo.Lock();
|
| - // If we're already at 0, we have a problem, so we check if we're >=.
|
| - DCHECK_GT(worker_thread_ref_count_, 0);
|
| -
|
| - // If this was our last reference, we delete the thread. This is okay even if
|
| - // we increment the count again, because the thread is created on the "first"
|
| - // FireEventToBroker, thus it will be created again if needed.
|
| - if (--worker_thread_ref_count_ == 0) {
|
| - if (worker_thread_ != NULL) {
|
| - // Store the worker_thread to a temporary pointer. It will be freed later.
|
| - thread = worker_thread_;
|
| - worker_thread_ = NULL;
|
| - }
|
| - }
|
| - m_csStaticDataInitAndTypeInfo.Unlock();
|
| -
|
| - // Clean the thread after the unlock to be certain we don't get a deadlock
|
| - // (the CriticalSection could be used in the worker thread).
|
| - if (thread) {
|
| - // It is OK to call Stop on a thread even when it isn't running.
|
| - thread->Stop();
|
| - delete thread;
|
| - }
|
| -}
|
| -
|
| -void ToolbandModule::EnsureThreadStarted() {
|
| - m_csStaticDataInitAndTypeInfo.Lock();
|
| - if (worker_thread_ == NULL) {
|
| - worker_thread_ = new ComWorkerThread;
|
| - // The COM worker thread must be a UI thread so that it can pump windows
|
| - // messages and allow COM to handle cross apartment calls.
|
| - worker_thread_->StartWithOptions(base::Thread::Options(MessageLoop::TYPE_UI,
|
| - 0)); // stack_size
|
| - }
|
| - m_csStaticDataInitAndTypeInfo.Unlock();
|
| -}
|
| -
|
| -void ToolbandModule::FireEventToBroker(const std::string& event_name,
|
| - const std::string& event_args) {
|
| - EnsureThreadStarted();
|
| - DCHECK(worker_thread_ != NULL);
|
| - MessageLoop* message_loop = worker_thread_->message_loop();
|
| - if (message_loop) {
|
| - message_loop->PostTask(FROM_HERE,
|
| - new FireEventTask(worker_thread_, event_name, event_args));
|
| - } else {
|
| - LOG(ERROR) << "Trying to post a message before the COM worker thread is"
|
| - "completely initialized and ready.";
|
| - }
|
| -}
|
| -
|
| -
|
| -ToolbandModule::ComWorkerThread::ComWorkerThread()
|
| - : 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_rpc_.Disconnect();
|
| -}
|
| -
|
| -void ToolbandModule::ComWorkerThread::FireEventToBroker(BSTR event_name,
|
| - BSTR event_args) {
|
| - DCHECK(broker_rpc_.is_connected());
|
| - bool result = broker_rpc_.FireEvent(event_name, event_args);
|
| - DCHECK(result);
|
| -}
|
| -
|
| ToolbandModule module;
|
|
|
| -void ceee_module_util::AddRefModuleWorkerThread() {
|
| - module.IncThreadRefCount();
|
| -}
|
| -void ceee_module_util::ReleaseModuleWorkerThread() {
|
| - module.DecThreadRefCount();
|
| -}
|
| -
|
| -void ceee_module_util::FireEventToBroker(const std::string& event_name,
|
| - const std::string& event_args) {
|
| - module.FireEventToBroker(event_name, event_args);
|
| -}
|
| -
|
| void ceee_module_util::Lock() {
|
| module.m_csStaticDataInitAndTypeInfo.Lock();
|
| }
|
|
|