diff options
Diffstat (limited to 'ceee/ie/broker/chrome_postman.h')
-rw-r--r-- | ceee/ie/broker/chrome_postman.h | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/ceee/ie/broker/chrome_postman.h b/ceee/ie/broker/chrome_postman.h new file mode 100644 index 0000000..538abd7 --- /dev/null +++ b/ceee/ie/broker/chrome_postman.h @@ -0,0 +1,133 @@ +// 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. +// +// @file +// Broke Postman implementation. + +#ifndef CEEE_IE_BROKER_CHROME_POSTMAN_H_ +#define CEEE_IE_BROKER_CHROME_POSTMAN_H_ + +#include "base/singleton.h" +#include "base/thread.h" +#include "ceee/ie/common/chrome_frame_host.h" + +#include "broker_lib.h" // NOLINT + +// The Broker Postman singleton object wrapping the ChromeFrameHost +// class so that it can receive API invocation from Chrome Frame, and also +// dispatch response and events to it. +// +// Since Chrome Frame must be access from a Single Thread Apartment, this +// object must only call it in an STA, so the PostMessage method must post a +// task to do so in the STA thread. +// +// But when Chrome Frame calls into this object, we can't block and thus +// the API invocations must be queued so that the API Dispatcher can +// fetch them from the queue, handle them appropriately in the MTA and +// post back the asynchronous response to Chrome Frame via our +// PostMessage method. + +class ChromePostman + : public CComObjectRootEx<CComMultiThreadModel>, + public IChromeFrameHostEvents { + public: + BEGIN_COM_MAP(ChromePostman) + END_COM_MAP() + + ChromePostman(); + virtual ~ChromePostman(); + + // This posts a tasks to our STA thread so that it posts the given message + // to Chrome Frame. + virtual void PostMessage(BSTR message, BSTR target); + + // This posts a tasks to the Api Invocation thread to fire the given event. + virtual void FireEvent(BSTR event_name, BSTR event_args); + + // This creates both an STA and an MTA threads. We must make sure we only call + // Chrome Frame from this STA. And since we can't block Chrome Frame we use + // the MTA thread to executes API Invocation we receive from Chrome Frame. + // We also create and initialize Chrome Framer from here. + virtual void Init(); + + // To cleanly terminate the threads, and our hooks into Chrome Frame. + virtual void Term(); + + // Returns our single instance held by the module. + static ChromePostman* GetInstance() { return single_instance_; } + + class ChromePostmanThread : public base::Thread { + public: + ChromePostmanThread(); + + // Called just prior to starting the message loop + virtual void Init(); + + // Called just after the message loop ends + virtual void CleanUp(); + + // Posts the message to our instance of Chrome Frame. + // THIS CAN ONLY BE CALLED FROM OUR THREAD, and we DCHECK it. + void PostMessage(BSTR message, BSTR target); + + // Retrieves the Chrome Frame host; should only be called from the + // postman thread. + void GetHost(IChromeFrameHost** host); + + // Resets Chrome Frame by tearing it down and restarting it. + // We use this when we receive a channel error meaning Chrome has died. + void ResetChromeFrame(); + + protected: + // Creates and initializes the chrome frame host. + // CAN ONLY BE CALLED FROM THE STA! + HRESULT InitializeChromeFrameHost(); + + // Isolate the creation of the host so we can overload it to mock + // the Chrome Frame Host in our tests. + // CAN ONLY BE CALLED FROM THE STA! + virtual HRESULT CreateChromeFrameHost(); + + // Tears down the Chrome Frame host. + void TeardownChromeFrameHost(); + + // The Chrome Frame host handling a Chrome Frame instance for us. + CComPtr<IChromeFrameHost> chrome_frame_host_; + }; + + protected: + // Messages received from Chrome Frame are sent to the API dispatcher via + // a task posted to our MTA thread. + HRESULT OnCfReadyStateChanged(LONG state); + HRESULT OnCfPrivateMessage(BSTR msg, BSTR origin, BSTR target); + HRESULT OnCfExtensionReady(BSTR path, int response); + HRESULT OnCfGetEnabledExtensionsComplete(SAFEARRAY* tab_delimited_paths); + HRESULT OnCfGetExtensionApisToAutomate(BSTR* functions_enabled); + HRESULT OnCfChannelError(); + + class ApiInvocationWorkerThread : public base::Thread { + public: + ApiInvocationWorkerThread(); + + // Called just prior to starting the message loop + virtual void Init(); + + // Called just after the message loop ends + virtual void CleanUp(); + }; + + // The STA in which we run. + ChromePostmanThread chrome_postman_thread_; + + // The MTA thread to which we post API Invocations and Fired Events. + ApiInvocationWorkerThread api_worker_thread_; + + // The number of times we tried to launch ChromeFrame. + int frame_reset_count_; + + // "in the end, there should be only one!" :-) + static ChromePostman* single_instance_; +}; + +#endif // CEEE_IE_BROKER_CHROME_POSTMAN_H_ |