Index: chrome_frame/protocol_sink_wrap.h |
=================================================================== |
--- chrome_frame/protocol_sink_wrap.h (revision 0) |
+++ chrome_frame/protocol_sink_wrap.h (revision 0) |
@@ -0,0 +1,221 @@ |
+// Copyright (c) 2009 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. |
+ |
+#ifndef CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ |
+#define CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ |
+ |
+#include <exdisp.h> |
+#include <urlmon.h> |
+#include <atlbase.h> |
+#include <atlcom.h> |
+#include <map> |
+#include <string> |
+ |
+#include "base/basictypes.h" |
+#include "base/ref_counted.h" |
+#include "base/scoped_comptr_win.h" |
+#include "googleurl/src/gurl.h" |
+#include "chrome_frame/ie8_types.h" |
+ |
+// Typedefs for IInternetProtocol and related methods that we patch. |
+typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Start_Fn)( |
+ IInternetProtocol* this_object, LPCWSTR url, |
+ IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, |
+ DWORD flags, HANDLE_PTR reserved); |
+typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Read_Fn)( |
+ IInternetProtocol* this_object, void* buffer, ULONG size, |
+ ULONG* size_read); |
+typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_StartEx_Fn)( |
+ IInternetProtocolEx* this_object, IUri* uri, |
+ IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, |
+ DWORD flags, HANDLE_PTR reserved); |
+typedef HRESULT (STDMETHODCALLTYPE* InternetProtocolRoot_Continue_Fn)( |
+ IInternetProtocolRoot* me, PROTOCOLDATA* data); |
+ |
+// A class to wrap protocol sink in IInternetProtocol::Start[Ex] for |
+// HTTP and HTTPS protocols. |
+// |
+// This is an alternative to a mime filter and we have to do this in order |
+// to inspect initial portion of HTML for 'chrome' meta tag and report |
+// a different mime type in that case. |
+// |
+// We implement several documented interfaces |
+// supported by the original sink provided by urlmon. There are a few |
+// undocumented interfaces that we have chosen not to implement |
+// but delegate simply the QI. |
+class ProtocolSinkWrap |
+ : public CComObjectRootEx<CComMultiThreadModel>, |
+ public IInternetProtocolSink, |
+ public IInternetBindInfoEx, |
+ public IServiceProvider, |
+ public IAuthenticate, |
+ public IInternetProtocolEx, |
+ public IInternetPriority, |
+ public IWrappedProtocol, |
+ // public IPreBindingSupport, // undocumented |
+ // public ITransProtocolSink, // Undocumented |
+ // public ITransactionInternal, // undocumented |
+ public IUriContainer { |
+ public: |
+ |
+#define COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS(x) \ |
+ COM_INTERFACE_ENTRY_FUNC(_ATL_IIDOF(x), \ |
+ offsetofclass(x, _ComMapClass), \ |
+ IfDelegateSupports) |
+ |
+BEGIN_COM_MAP(ProtocolSinkWrap) |
+ COM_INTERFACE_ENTRY(IInternetProtocolSink) |
+ COM_INTERFACE_ENTRY(IInternetBindInfo) |
+ COM_INTERFACE_ENTRY(IInternetBindInfoEx) |
+ COM_INTERFACE_ENTRY(IServiceProvider) |
+ COM_INTERFACE_ENTRY(IAuthenticate) |
+ COM_INTERFACE_ENTRY(IInternetProtocolRoot) |
+ COM_INTERFACE_ENTRY(IInternetProtocol) |
+ COM_INTERFACE_ENTRY(IInternetProtocolEx) |
+ COM_INTERFACE_ENTRY(IInternetPriority) |
+ COM_INTERFACE_ENTRY(IWrappedProtocol) |
+ COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS(IUriContainer) |
+ COM_INTERFACE_ENTRY_FUNC_BLIND(0, CheckOutgoingInterface) |
+END_COM_MAP() |
+ |
+ ProtocolSinkWrap(); |
+ virtual ~ProtocolSinkWrap(); |
+ |
+ bool Initialize(IInternetProtocol* protocol, |
+ IInternetProtocolSink* original_sink, const wchar_t* url); |
+ |
+ static bool PatchProtocolHandler(const wchar_t* dll, |
+ const CLSID& handler_clsid); |
+ |
+ // IInternetProtocol/Ex patches. |
+ static HRESULT STDMETHODCALLTYPE OnStart(InternetProtocol_Start_Fn orig_start, |
+ IInternetProtocol* protocol, LPCWSTR url, |
+ IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, |
+ DWORD flags, HANDLE_PTR reserved); |
+ |
+ static HRESULT STDMETHODCALLTYPE OnStartEx( |
+ InternetProtocol_StartEx_Fn orig_start_ex, IInternetProtocolEx* protocol, |
+ IUri* uri, IInternetProtocolSink* prot_sink, |
+ IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved); |
+ |
+ static HRESULT STDMETHODCALLTYPE OnRead(InternetProtocol_Read_Fn orig_read, |
+ IInternetProtocol* protocol, void* buffer, ULONG size, ULONG* size_read); |
+ |
+ // IInternetProtocolSink methods |
+ STDMETHOD(Switch)(PROTOCOLDATA* protocol_data); |
+ STDMETHOD(ReportProgress)(ULONG status_code, LPCWSTR status_text); |
+ STDMETHOD(ReportData)(DWORD flags, ULONG progress, ULONG max_progress); |
+ STDMETHOD(ReportResult)(HRESULT result, DWORD error, LPCWSTR result_text); |
+ |
+ // IInternetBindInfoEx |
+ STDMETHOD(GetBindInfo)(DWORD* flags, BINDINFO* bind_info); |
+ STDMETHOD(GetBindString)(ULONG string_type, LPOLESTR* string_array, |
+ ULONG array_size, ULONG* size_returned); |
+ STDMETHOD(GetBindInfoEx)(DWORD *flags, BINDINFO* bind_info, |
+ DWORD* bindf2, DWORD *reserved); |
+ |
+ // IServiceProvider |
+ STDMETHOD(QueryService)(REFGUID service_guid, REFIID riid, void** service); |
+ |
+ // IAuthenticate |
+ STDMETHOD(Authenticate)(HWND* window, LPWSTR* user_name, LPWSTR* password); |
+ |
+ // IInternetProtocolEx |
+ STDMETHOD(Start)(LPCWSTR url, IInternetProtocolSink *protocol_sink, |
+ IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved); |
+ STDMETHOD(Continue)(PROTOCOLDATA* protocol_data); |
+ STDMETHOD(Abort)(HRESULT reason, DWORD options); |
+ STDMETHOD(Terminate)(DWORD options); |
+ STDMETHOD(Suspend)(); |
+ STDMETHOD(Resume)(); |
+ STDMETHOD(Read)(void *buffer, ULONG size, ULONG* size_read); |
+ STDMETHOD(Seek)(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER* new_pos); |
+ STDMETHOD(LockRequest)(DWORD options); |
+ STDMETHOD(UnlockRequest)(); |
+ STDMETHOD(StartEx)(IUri* uri, IInternetProtocolSink* protocol_sink, |
+ IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved); |
+ |
+ // IInternetPriority |
+ STDMETHOD(SetPriority)(LONG priority); |
+ STDMETHOD(GetPriority)(LONG* priority); |
+ |
+ // IWrappedProtocol |
+ STDMETHOD(GetWrapperCode)(LONG *code, DWORD_PTR reserved); |
+ |
+ // public IUriContainer |
+ STDMETHOD(GetIUri)(IUri** uri); |
+ |
+ // IPreBindingSupport, // undocumented |
+ // ITransProtocolSink, // Undocumented |
+ // ITransactionInternal, // undocumented |
+ |
+ protected: |
+ enum RendererType { |
+ UNDETERMINED, |
+ CHROME, |
+ OTHER |
+ }; |
+ |
+ typedef std::map<IInternetProtocol*, ProtocolSinkWrap*> ProtocolSinkMap; |
+ static const int kMaxContentSniffLength = 1024; |
+ |
+ static scoped_refptr<ProtocolSinkWrap> InstanceFromProtocol( |
+ IInternetProtocol* protocol); |
+ static HRESULT WebBrowserFromProtocolSink(IInternetProtocolSink* sink, |
+ IWebBrowser2** web_browser); |
+ static ScopedComPtr<IInternetProtocolSink> MaybeWrapSink( |
+ IInternetProtocol* protocol, IInternetProtocolSink* prot_sink, |
+ const wchar_t* url); |
+ static HRESULT WINAPI CheckOutgoingInterface(void* obj, REFIID iid, |
+ LPVOID* ret, DWORD cookie); |
+ static HRESULT WINAPI IfDelegateSupports(void* obj, REFIID iid, |
+ LPVOID* ret, DWORD cookie); |
+ |
+ void DetermineRendererType(); |
+ HRESULT OnReadImpl(void* buffer, ULONG size, ULONG* size_read, |
+ InternetProtocol_Read_Fn orig_read); |
+ |
+ bool is_undetermined() const { |
+ return (UNDETERMINED == renderer_type_); |
+ } |
+ RendererType renderer_type() const { |
+ return renderer_type_; |
+ } |
+ |
+ // WARNING: Don't use GURL variables here. Please see |
+ // http://b/issue?id=2102171 for details. |
+ |
+ // Remember original sink |
+ CComPtr<IInternetProtocolSink> delegate_; |
+ // Cannot take a reference on the protocol. |
+ IInternetProtocol* protocol_; |
+ RendererType renderer_type_; |
+ |
+ // Buffer for accumulated data including 1 extra for NULL-terminator |
+ char buffer_[kMaxContentSniffLength + 1]; |
+ unsigned long buffer_size_; |
+ unsigned long buffer_pos_; |
+ |
+ // Accumulated result |
+ bool is_saved_result_; |
+ HRESULT result_code_; |
+ DWORD result_error_; |
+ std::wstring result_text_; |
+ // For tracking re-entrency and preventing duplicate Read()s from |
+ // distorting the outcome of ReportData. |
+ int report_data_recursiveness_; |
+ |
+ static ProtocolSinkMap sink_map_; |
+ // TODO(joshia): Replace with Lock |
+ static CComAutoCriticalSection sink_map_lock_; |
+ |
+ std::wstring url_; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(ProtocolSinkWrap); |
+}; |
+ |
+ |
+#endif // CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ |
+ |