| Index: chrome_frame/urlmon_url_request.h
|
| ===================================================================
|
| --- chrome_frame/urlmon_url_request.h (revision 37418)
|
| +++ chrome_frame/urlmon_url_request.h (working copy)
|
| @@ -8,263 +8,77 @@
|
| #include <urlmon.h>
|
| #include <atlbase.h>
|
| #include <atlcom.h>
|
| -#include <atlwin.h>
|
| -#include <algorithm>
|
| #include <string>
|
|
|
| -#include "base/lock.h"
|
| -#include "base/platform_thread.h"
|
| -#include "base/thread.h"
|
| #include "base/scoped_comptr_win.h"
|
| +#include "base/thread.h"
|
| +#include "base/waitable_event.h"
|
| #include "chrome_frame/plugin_url_request.h"
|
| -#include "chrome_frame/chrome_frame_delegate.h"
|
| +#include "chrome_frame/utils.h"
|
|
|
| -#include "net/base/net_errors.h"
|
| -#include "net/base/upload_data.h"
|
| +class UrlmonUrlRequest;
|
|
|
| -class UrlmonUrlRequest
|
| - : public CComObjectRootEx<CComMultiThreadModel>,
|
| - public PluginUrlRequest,
|
| - public IServiceProviderImpl<UrlmonUrlRequest>,
|
| - public IBindStatusCallback,
|
| - public IHttpNegotiate,
|
| - public IAuthenticate,
|
| - public IHttpSecurity,
|
| - public CWindowImpl<UrlmonUrlRequest>,
|
| - public TaskMarshallerThroughWindowsMessages<UrlmonUrlRequest> {
|
| +class UrlmonUrlRequestManager :
|
| + public PluginUrlRequestManager,
|
| + public PluginUrlRequestDelegate {
|
| public:
|
| - typedef TaskMarshallerThroughWindowsMessages<UrlmonUrlRequest>
|
| - TaskMarshaller;
|
| + UrlmonUrlRequestManager();
|
| + ~UrlmonUrlRequestManager();
|
|
|
| - UrlmonUrlRequest();
|
| - ~UrlmonUrlRequest();
|
| + // Use specific moniker and bind context when Chrome request this url.
|
| + // Used from ChromeActiveDocument's implementation of IPersistMoniker::Load().
|
| + void UseMonikerForUrl(IMoniker* moniker, IBindCtx* bind_ctx,
|
| + const std::wstring& url);
|
| + void StealMonikerFromRequest(int request_id, IMoniker** moniker);
|
|
|
| -BEGIN_COM_MAP(UrlmonUrlRequest)
|
| - COM_INTERFACE_ENTRY(IHttpNegotiate)
|
| - COM_INTERFACE_ENTRY(IServiceProvider)
|
| - COM_INTERFACE_ENTRY(IBindStatusCallback)
|
| - COM_INTERFACE_ENTRY(IWindowForBindingUI)
|
| - COM_INTERFACE_ENTRY(IAuthenticate)
|
| - COM_INTERFACE_ENTRY(IHttpSecurity)
|
| -END_COM_MAP()
|
| + private:
|
| + struct MonikerForUrl {
|
| + ScopedComPtr<IMoniker> moniker;
|
| + ScopedComPtr<IBindCtx> bind_ctx;
|
| + std::wstring url;
|
| + };
|
|
|
| -BEGIN_SERVICE_MAP(UrlmonUrlRequest)
|
| - SERVICE_ENTRY(IID_IHttpNegotiate);
|
| -END_SERVICE_MAP()
|
| + friend class MessageLoop;
|
| + friend struct RunnableMethodTraits<UrlmonUrlRequestManager>;
|
| + static bool ImplementsThreadSafeReferenceCounting() { return true; }
|
| + void AddRef() {}
|
| + void Release() {}
|
|
|
| -BEGIN_MSG_MAP(UrlmonUrlRequest)
|
| - CHAIN_MSG_MAP(TaskMarshaller)
|
| -END_MSG_MAP()
|
| + // PluginUrlRequestManager implementation.
|
| + virtual bool IsThreadSafe();
|
| + virtual void StartRequest(int request_id,
|
| + const IPC::AutomationURLRequest& request_info);
|
| + virtual void ReadRequest(int request_id, int bytes_to_read);
|
| + virtual void EndRequest(int request_id);
|
| + virtual void StopAll();
|
|
|
| - // PluginUrlRequest implementation
|
| - virtual bool Start();
|
| - virtual void Stop();
|
| - virtual bool Read(int bytes_to_read);
|
| + // PluginUrlRequestDelegate implementation
|
| + virtual void OnResponseStarted(int request_id, const char* mime_type,
|
| + const char* headers, int size, base::Time last_modified,
|
| + const std::string& peristent_cookies, const std::string& redirect_url,
|
| + int redirect_status);
|
| + virtual void OnReadComplete(int request_id, const void* buffer, int len);
|
| + virtual void OnResponseEnd(int request_id, const URLRequestStatus& status);
|
|
|
| - void TransferToHost(IUnknown* host);
|
| + // Methods executed in worker thread.
|
| + void StartRequestWorker(int request_id,
|
| + const IPC::AutomationURLRequest& request_info,
|
| + MonikerForUrl* moniker_for_url);
|
| + void ReadRequestWorker(int request_id, int bytes_to_read);
|
| + void EndRequestWorker(int request_id);
|
| + void StopAllWorker();
|
| + void StealMonikerFromRequestWorker(int request_id, IMoniker** moniker,
|
| + base::WaitableEvent* done);
|
|
|
| - // IBindStatusCallback implementation
|
| - STDMETHOD(OnStartBinding)(DWORD reserved, IBinding* binding);
|
| - STDMETHOD(GetPriority)(LONG* priority);
|
| - STDMETHOD(OnLowResource)(DWORD reserved);
|
| - STDMETHOD(OnProgress)(ULONG progress, ULONG max_progress,
|
| - ULONG status_code, LPCWSTR status_text);
|
| - STDMETHOD(OnStopBinding)(HRESULT result, LPCWSTR error);
|
| - STDMETHOD(GetBindInfo)(DWORD* bind_flags, BINDINFO* bind_info);
|
| - STDMETHOD(OnDataAvailable)(DWORD flags, DWORD size, FORMATETC* formatetc,
|
| - STGMEDIUM* storage);
|
| - STDMETHOD(OnObjectAvailable)(REFIID iid, IUnknown* object);
|
| + // Map for (request_id <-> UrlmonUrlRequest)
|
| + typedef std::map<int, scoped_refptr<UrlmonUrlRequest> > RequestMap;
|
| + RequestMap request_map_;
|
| + scoped_refptr<UrlmonUrlRequest> LookupRequest(int request_id);
|
|
|
| - // IHttpNegotiate implementation
|
| - STDMETHOD(BeginningTransaction)(const wchar_t* url,
|
| - const wchar_t* current_headers, DWORD reserved,
|
| - wchar_t** additional_headers);
|
| - STDMETHOD(OnResponse)(DWORD dwResponseCode, const wchar_t* response_headers,
|
| - const wchar_t* request_headers, wchar_t** additional_headers);
|
| -
|
| - // IWindowForBindingUI implementation. This interface is used typically to
|
| - // query the window handle which URLMON uses as the parent of error dialogs.
|
| - STDMETHOD(GetWindow)(REFGUID guid_reason, HWND* parent_window);
|
| -
|
| - // IAuthenticate implementation. Used to return the parent window for the
|
| - // dialog displayed by IE for authenticating with a proxy.
|
| - STDMETHOD(Authenticate)(HWND* parent_window, LPWSTR* user_name,
|
| - LPWSTR* password);
|
| -
|
| - // IHttpSecurity implementation.
|
| - STDMETHOD(OnSecurityProblem)(DWORD problem);
|
| -
|
| - HRESULT ConnectToExistingMoniker(IMoniker* moniker, IBindCtx* context,
|
| - const std::wstring& url);
|
| -
|
| - void set_parent_window(HWND parent_window) {
|
| - parent_window_ = parent_window;
|
| - }
|
| -
|
| - // Needed to support PostTask.
|
| - static bool ImplementsThreadSafeReferenceCounting() {
|
| - return true;
|
| - }
|
| -
|
| - // URL requests are handled on this thread.
|
| - void set_worker_thread(base::Thread* worker_thread) {
|
| - worker_thread_ = worker_thread;
|
| - }
|
| -
|
| - virtual void OnFinalMessage(HWND window);
|
| -
|
| - protected:
|
| - // The following functions issue and handle Urlmon requests on the dedicated
|
| - // Urlmon thread.
|
| - void StartAsync();
|
| - void StopAsync();
|
| - void ReadAsync(int bytes_to_read);
|
| - void ReleaseBindings();
|
| -
|
| - static const size_t kCopyChunkSize = 32 * 1024;
|
| - // URL requests are handled on this thread.
|
| - base::Thread* worker_thread_;
|
| -
|
| - // A fake stream class to make it easier to copy received data using
|
| - // IStream::CopyTo instead of allocating temporary buffers and keeping
|
| - // track of data copied so far.
|
| - class SendStream
|
| - : public CComObjectRoot,
|
| - public IStream {
|
| - public:
|
| - SendStream() {
|
| - }
|
| -
|
| - BEGIN_COM_MAP(SendStream)
|
| - COM_INTERFACE_ENTRY(IStream)
|
| - COM_INTERFACE_ENTRY(ISequentialStream)
|
| - END_COM_MAP()
|
| -
|
| - void Initialize(UrlmonUrlRequest* request) {
|
| - request_ = request;
|
| - }
|
| -
|
| - STDMETHOD(Read)(void* pv, ULONG cb, ULONG* read) {
|
| - DCHECK(false) << __FUNCTION__;
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - STDMETHOD(Write)(const void * buffer, ULONG size, ULONG* size_written) {
|
| - DCHECK(request_);
|
| - int size_to_write = static_cast<int>(
|
| - std::min(static_cast<ULONG>(MAXINT), size));
|
| - request_->OnReadComplete(buffer, size_to_write);
|
| - if (size_written)
|
| - *size_written = size_to_write;
|
| - return S_OK;
|
| - }
|
| -
|
| - STDMETHOD(Seek)(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER* new_pos) {
|
| - DCHECK(false) << __FUNCTION__;
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - STDMETHOD(SetSize)(ULARGE_INTEGER new_size) {
|
| - DCHECK(false) << __FUNCTION__;
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - STDMETHOD(CopyTo)(IStream* stream, ULARGE_INTEGER cb, ULARGE_INTEGER* read,
|
| - ULARGE_INTEGER* written) {
|
| - DCHECK(false) << __FUNCTION__;
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - STDMETHOD(Commit)(DWORD flags) {
|
| - DCHECK(false) << __FUNCTION__;
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - STDMETHOD(Revert)() {
|
| - DCHECK(false) << __FUNCTION__;
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - STDMETHOD(LockRegion)(ULARGE_INTEGER offset, ULARGE_INTEGER cb,
|
| - DWORD type) {
|
| - DCHECK(false) << __FUNCTION__;
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - STDMETHOD(UnlockRegion)(ULARGE_INTEGER offset, ULARGE_INTEGER cb,
|
| - DWORD type) {
|
| - DCHECK(false) << __FUNCTION__;
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag) {
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - STDMETHOD(Clone)(IStream** stream) {
|
| - DCHECK(false) << __FUNCTION__;
|
| - return E_NOTIMPL;
|
| - }
|
| -
|
| - protected:
|
| - scoped_refptr<UrlmonUrlRequest> request_;
|
| - DISALLOW_COPY_AND_ASSIGN(SendStream);
|
| - };
|
| -
|
| - // Manage data caching. Note: this class supports cache
|
| - // size less than 2GB
|
| - class Cache {
|
| - public:
|
| - // Adds data to the end of the cache.
|
| - bool Append(IStream* source, size_t* bytes_copied);
|
| -
|
| - // Reads from the cache.
|
| - bool Read(IStream* dest, size_t size, size_t* bytes_copied);
|
| -
|
| - // Returns the size of the cache.
|
| - size_t Size() const;
|
| -
|
| - // Returns true if the cache has valid data.
|
| - bool is_valid() const {
|
| - return Size() != 0;
|
| - }
|
| -
|
| - protected:
|
| - std::vector<byte> cache_;
|
| - char read_buffer_[kCopyChunkSize];
|
| - };
|
| -
|
| - HRESULT StartAsyncDownload();
|
| - // Sends over the response end notification to chrome, releases the bindings
|
| - // and releases the initial reference on the UrlmonUrlRequest object.
|
| - // After this function is called we should not attempt to access any members
|
| - // as the object could become invalid at any point.
|
| - void EndRequest();
|
| - // Executes in the context of the UI thread and releases the outstanding
|
| - // reference to us. It also deletes the request mapping for this instance.
|
| - void EndRequestInternal();
|
| - int GetHttpResponseStatus() const;
|
| - std::string GetHttpHeaders() const;
|
| -
|
| - static net::Error HresultToNetError(HRESULT hr);
|
| -
|
| - private:
|
| - std::wstring redirect_url_;
|
| - int redirect_status_;
|
| - ScopedComPtr<IBinding> binding_;
|
| - ScopedComPtr<IMoniker> moniker_;
|
| - ScopedComPtr<IBindCtx> bind_context_;
|
| - Cache cached_data_;
|
| - size_t pending_read_size_;
|
| - URLRequestStatus status_;
|
| -
|
| - PlatformThreadId thread_;
|
| - static int instance_count_;
|
| - HWND parent_window_;
|
| - // Set to true if a redirect notification was aborted.
|
| - bool ignore_redirect_stop_binding_error_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(UrlmonUrlRequest);
|
| + scoped_ptr<MonikerForUrl> moniker_for_url_;
|
| + STAThread worker_thread_;
|
| + base::WaitableEvent map_empty_;
|
| + bool stopping_;
|
| };
|
|
|
| #endif // CHROME_FRAME_URLMON_URL_REQUEST_H_
|
|
|