| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ | 5 #ifndef CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ |
| 6 #define CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ | 6 #define CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ |
| 7 | 7 |
| 8 #include <exdisp.h> | 8 #include <exdisp.h> |
| 9 #include <urlmon.h> | 9 #include <urlmon.h> |
| 10 #include <atlbase.h> | 10 #include <atlbase.h> |
| 11 #include <atlcom.h> | 11 #include <atlcom.h> |
| 12 | 12 |
| 13 #include <map> | 13 #include <map> |
| 14 #include <string> | 14 #include <string> |
| 15 | 15 |
| 16 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
| 17 #include "base/ref_counted.h" | 17 #include "base/ref_counted.h" |
| 18 #include "base/scoped_comptr_win.h" | 18 #include "base/scoped_comptr_win.h" |
| 19 #include "base/scoped_bstr_win.h" |
| 19 #include "googleurl/src/gurl.h" | 20 #include "googleurl/src/gurl.h" |
| 20 #include "chrome_frame/chrome_frame_delegate.h" | 21 #include "chrome_frame/chrome_frame_delegate.h" |
| 21 #include "chrome_frame/ie8_types.h" | 22 #include "chrome_frame/ie8_types.h" |
| 22 #include "chrome_frame/utils.h" | 23 #include "chrome_frame/utils.h" |
| 23 #include "chrome_frame/vtable_patch_manager.h" | 24 #include "chrome_frame/vtable_patch_manager.h" |
| 24 | 25 |
| 25 // Typedefs for IInternetProtocol and related methods that we patch. | 26 // Typedefs for IInternetProtocol and related methods that we patch. |
| 26 typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Start_Fn)( | 27 typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Start_Fn)( |
| 27 IInternetProtocol* this_object, LPCWSTR url, | 28 IInternetProtocol* this_object, LPCWSTR url, |
| 28 IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, | 29 IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, |
| 29 DWORD flags, HANDLE_PTR reserved); | 30 DWORD flags, HANDLE_PTR reserved); |
| 30 typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Read_Fn)( | 31 typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Read_Fn)( |
| 31 IInternetProtocol* this_object, void* buffer, ULONG size, | 32 IInternetProtocol* this_object, void* buffer, ULONG size, |
| 32 ULONG* size_read); | 33 ULONG* size_read); |
| 33 typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_StartEx_Fn)( | 34 typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_StartEx_Fn)( |
| 34 IInternetProtocolEx* this_object, IUri* uri, | 35 IInternetProtocolEx* this_object, IUri* uri, |
| 35 IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, | 36 IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, |
| 36 DWORD flags, HANDLE_PTR reserved); | 37 DWORD flags, HANDLE_PTR reserved); |
| 37 typedef HRESULT (STDMETHODCALLTYPE* InternetProtocolRoot_Continue_Fn)( | 38 typedef HRESULT (STDMETHODCALLTYPE* InternetProtocolRoot_Continue_Fn)( |
| 38 IInternetProtocolRoot* me, PROTOCOLDATA* data); | 39 IInternetProtocolRoot* me, PROTOCOLDATA* data); |
| 39 | 40 |
| 41 |
| 42 enum RendererType { |
| 43 UNDETERMINED, |
| 44 CHROME, |
| 45 OTHER |
| 46 }; |
| 47 |
| 48 class ProtData; |
| 49 |
| 40 // A class to wrap protocol sink in IInternetProtocol::Start[Ex] for | 50 // A class to wrap protocol sink in IInternetProtocol::Start[Ex] for |
| 41 // HTTP and HTTPS protocols. | 51 // HTTP and HTTPS protocols. |
| 42 // | 52 // |
| 43 // This is an alternative to a mime filter and we have to do this in order | 53 // This is an alternative to a mime filter and we have to do this in order |
| 44 // to inspect initial portion of HTML for 'chrome' meta tag and report | 54 // to inspect initial portion of HTML for 'chrome' meta tag and report |
| 45 // a different mime type in that case. | 55 // a different mime type in that case. |
| 46 // | 56 // |
| 47 // We implement several documented interfaces | 57 // We implement several documented interfaces |
| 48 // supported by the original sink provided by urlmon. There are a few | 58 // supported by the original sink provided by urlmon. There are a few |
| 49 // undocumented interfaces that we have chosen not to implement | 59 // undocumented interfaces that we have chosen not to implement |
| 50 // but delegate simply the QI. | 60 // but delegate simply the QI. |
| 51 class ProtocolSinkWrap | 61 class ProtocolSinkWrap |
| 52 : public CComObjectRootEx<CComMultiThreadModel>, | 62 : public CComObjectRootEx<CComMultiThreadModel>, |
| 53 public IInternetProtocolSink, | 63 public IInternetProtocolSink { |
| 54 public IInternetBindInfoEx, | |
| 55 public IServiceProvider, | |
| 56 public IAuthenticate, | |
| 57 public IInternetProtocolEx, | |
| 58 public IInternetPriority, | |
| 59 public IWrappedProtocol, | |
| 60 // public IPreBindingSupport, // undocumented | |
| 61 // public ITransProtocolSink, // Undocumented | |
| 62 // public ITransactionInternal, // undocumented | |
| 63 public IUriContainer { | |
| 64 public: | 64 public: |
| 65 | 65 |
| 66 BEGIN_COM_MAP(ProtocolSinkWrap) | 66 BEGIN_COM_MAP(ProtocolSinkWrap) |
| 67 COM_INTERFACE_ENTRY(IInternetProtocolSink) | 67 COM_INTERFACE_ENTRY(IInternetProtocolSink) |
| 68 COM_INTERFACE_ENTRY(IInternetBindInfo) | |
| 69 COM_INTERFACE_ENTRY(IInternetBindInfoEx) | |
| 70 COM_INTERFACE_ENTRY(IServiceProvider) | |
| 71 COM_INTERFACE_ENTRY(IAuthenticate) | |
| 72 COM_INTERFACE_ENTRY(IInternetProtocolRoot) | |
| 73 COM_INTERFACE_ENTRY(IInternetProtocol) | |
| 74 COM_INTERFACE_ENTRY(IInternetProtocolEx) | |
| 75 COM_INTERFACE_ENTRY(IInternetPriority) | |
| 76 COM_INTERFACE_ENTRY(IWrappedProtocol) | |
| 77 COM_INTERFACE_ENTRY_IF_DELEGATE_SUPPORTS(IUriContainer) | |
| 78 COM_INTERFACE_BLIND_DELEGATE() | 68 COM_INTERFACE_BLIND_DELEGATE() |
| 79 END_COM_MAP() | 69 END_COM_MAP() |
| 80 | 70 |
| 71 static ScopedComPtr<IInternetProtocolSink> CreateNewSink( |
| 72 IInternetProtocolSink* sink, ProtData* prot_data); |
| 73 |
| 74 // Apparently this has to be public, to satisfy COM_INTERFACE_BLIND_DELEGATE |
| 75 IInternetProtocolSink* delegate() { |
| 76 return delegate_; |
| 77 } |
| 78 |
| 79 protected: |
| 81 ProtocolSinkWrap(); | 80 ProtocolSinkWrap(); |
| 82 virtual ~ProtocolSinkWrap(); | 81 ~ProtocolSinkWrap(); |
| 83 | 82 |
| 84 bool Initialize(IInternetProtocol* protocol, | 83 private: |
| 85 IInternetProtocolSink* original_sink, const wchar_t* url); | |
| 86 | |
| 87 // VTable patches the IInternetProtocol and IIntenetProtocolEx interface. | |
| 88 // Returns true on success. | |
| 89 static bool PatchProtocolHandlers(); | |
| 90 | |
| 91 // Unpatches the IInternetProtocol and IInternetProtocolEx interfaces. | |
| 92 static void UnpatchProtocolHandlers(); | |
| 93 | |
| 94 // IInternetProtocol/Ex patches. | |
| 95 static STDMETHODIMP OnStart(InternetProtocol_Start_Fn orig_start, | |
| 96 IInternetProtocol* protocol, LPCWSTR url, | |
| 97 IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, | |
| 98 DWORD flags, HANDLE_PTR reserved); | |
| 99 | |
| 100 static STDMETHODIMP OnStartEx( | |
| 101 InternetProtocol_StartEx_Fn orig_start_ex, IInternetProtocolEx* protocol, | |
| 102 IUri* uri, IInternetProtocolSink* prot_sink, | |
| 103 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved); | |
| 104 | |
| 105 static STDMETHODIMP OnRead(InternetProtocol_Read_Fn orig_read, | |
| 106 IInternetProtocol* protocol, void* buffer, ULONG size, ULONG* size_read); | |
| 107 | |
| 108 // IInternetProtocolSink methods | 84 // IInternetProtocolSink methods |
| 109 STDMETHOD(Switch)(PROTOCOLDATA* protocol_data); | 85 STDMETHOD(Switch)(PROTOCOLDATA* protocol_data); |
| 110 STDMETHOD(ReportProgress)(ULONG status_code, LPCWSTR status_text); | 86 STDMETHOD(ReportProgress)(ULONG status_code, LPCWSTR status_text); |
| 111 STDMETHOD(ReportData)(DWORD flags, ULONG progress, ULONG max_progress); | 87 STDMETHOD(ReportData)(DWORD flags, ULONG progress, ULONG max_progress); |
| 112 STDMETHOD(ReportResult)(HRESULT result, DWORD error, LPCWSTR result_text); | 88 STDMETHOD(ReportResult)(HRESULT result, DWORD error, LPCWSTR result_text); |
| 113 | 89 |
| 114 // IInternetBindInfoEx | 90 // Remember original sink |
| 115 STDMETHOD(GetBindInfo)(DWORD* flags, BINDINFO* bind_info); | 91 ScopedComPtr<IInternetProtocolSink> delegate_; |
| 116 STDMETHOD(GetBindString)(ULONG string_type, LPOLESTR* string_array, | 92 scoped_refptr<ProtData> prot_data_; |
| 117 ULONG array_size, ULONG* size_returned); | 93 DISALLOW_COPY_AND_ASSIGN(ProtocolSinkWrap); |
| 118 STDMETHOD(GetBindInfoEx)(DWORD *flags, BINDINFO* bind_info, | 94 }; |
| 119 DWORD* bindf2, DWORD *reserved); | |
| 120 | 95 |
| 121 // IServiceProvider | 96 class ProtData : public base::RefCounted<ProtData> { |
| 122 STDMETHOD(QueryService)(REFGUID service_guid, REFIID riid, void** service); | 97 public: |
| 98 ProtData(IInternetProtocol* protocol, InternetProtocol_Read_Fn read_fun, |
| 99 const wchar_t* url); |
| 100 ~ProtData(); |
| 101 HRESULT Read(void* buffer, ULONG size, ULONG* size_read); |
| 102 HRESULT ReportProgress(IInternetProtocolSink* delegate, |
| 103 ULONG status_code, |
| 104 LPCWSTR status_text); |
| 105 HRESULT ReportData(IInternetProtocolSink* delegate, |
| 106 DWORD flags, ULONG progress, ULONG max_progress); |
| 107 HRESULT ReportResult(IInternetProtocolSink* delegate, HRESULT result, |
| 108 DWORD error, LPCWSTR result_text); |
| 109 void UpdateUrl(const wchar_t* url); |
| 110 static scoped_refptr<ProtData> DataFromProtocol(IInternetProtocol* protocol); |
| 123 | 111 |
| 124 // IAuthenticate | 112 RendererType renderer_type() { |
| 125 STDMETHOD(Authenticate)(HWND* window, LPWSTR* user_name, LPWSTR* password); | |
| 126 | |
| 127 // IInternetProtocolEx | |
| 128 STDMETHOD(Start)(LPCWSTR url, IInternetProtocolSink *protocol_sink, | |
| 129 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved); | |
| 130 STDMETHOD(Continue)(PROTOCOLDATA* protocol_data); | |
| 131 STDMETHOD(Abort)(HRESULT reason, DWORD options); | |
| 132 STDMETHOD(Terminate)(DWORD options); | |
| 133 STDMETHOD(Suspend)(); | |
| 134 STDMETHOD(Resume)(); | |
| 135 STDMETHOD(Read)(void *buffer, ULONG size, ULONG* size_read); | |
| 136 STDMETHOD(Seek)(LARGE_INTEGER move, DWORD origin, ULARGE_INTEGER* new_pos); | |
| 137 STDMETHOD(LockRequest)(DWORD options); | |
| 138 STDMETHOD(UnlockRequest)(); | |
| 139 STDMETHOD(StartEx)(IUri* uri, IInternetProtocolSink* protocol_sink, | |
| 140 IInternetBindInfo* bind_info, DWORD flags, HANDLE_PTR reserved); | |
| 141 | |
| 142 // IInternetPriority | |
| 143 STDMETHOD(SetPriority)(LONG priority); | |
| 144 STDMETHOD(GetPriority)(LONG* priority); | |
| 145 | |
| 146 // IWrappedProtocol | |
| 147 STDMETHOD(GetWrapperCode)(LONG *code, DWORD_PTR reserved); | |
| 148 | |
| 149 // public IUriContainer | |
| 150 STDMETHOD(GetIUri)(IUri** uri); | |
| 151 | |
| 152 // IPreBindingSupport, // undocumented | |
| 153 // ITransProtocolSink, // Undocumented | |
| 154 // ITransactionInternal, // undocumented | |
| 155 | |
| 156 IInternetProtocolSink* delegate() const { | |
| 157 return delegate_; | |
| 158 } | |
| 159 | |
| 160 protected: | |
| 161 enum RendererType { | |
| 162 UNDETERMINED, | |
| 163 CHROME, | |
| 164 OTHER | |
| 165 }; | |
| 166 | |
| 167 typedef std::map<IInternetProtocol*, ProtocolSinkWrap*> ProtocolSinkMap; | |
| 168 static const int kMaxContentSniffLength = 1024; | |
| 169 | |
| 170 static scoped_refptr<ProtocolSinkWrap> InstanceFromProtocol( | |
| 171 IInternetProtocol* protocol); | |
| 172 static ScopedComPtr<IInternetProtocolSink> MaybeWrapSink( | |
| 173 IInternetProtocol* protocol, IInternetProtocolSink* prot_sink, | |
| 174 const wchar_t* url); | |
| 175 | |
| 176 void DetermineRendererType(); | |
| 177 | |
| 178 HRESULT OnReadImpl(void* buffer, ULONG size, ULONG* size_read, | |
| 179 InternetProtocol_Read_Fn orig_read); | |
| 180 | |
| 181 // This function determines whether the current request should be handled | |
| 182 // by Chrome. If yes it reports the mime type as application/chromepage, | |
| 183 // which ensures that the ChromeFrame is instantiated for handling this | |
| 184 // request. | |
| 185 // Returns S_OK on success. | |
| 186 HRESULT CheckAndReportChromeMimeTypeForRequest(); | |
| 187 | |
| 188 bool is_undetermined() const { | |
| 189 return (UNDETERMINED == renderer_type_); | |
| 190 } | |
| 191 RendererType renderer_type() const { | |
| 192 return renderer_type_; | 113 return renderer_type_; |
| 193 } | 114 } |
| 194 | 115 |
| 195 // Creates an instance of the specified protocol handler and returns the | 116 private: |
| 196 // IInternetProtocol interface pointer. | 117 typedef std::map<IInternetProtocol*, ProtData*> ProtocolDataMap; |
| 197 // Returns S_OK on success. | 118 static ProtocolDataMap datamap_; |
| 198 static HRESULT CreateProtocolHandlerInstance(const CLSID& clsid, | 119 static Lock datamap_lock_; |
| 199 IInternetProtocol** protocol); | |
| 200 | 120 |
| 201 // Helper function for patching the VTable of the IInternetProtocol | 121 // Url we are retrieving. Used for IsOptInUrl() only. |
| 202 // interface. It instantiates the object identified by the protocol_clsid | 122 std::wstring url_; |
| 203 // parameter and patches its VTable. | 123 // Our gate to IInternetProtocol::Read() |
| 204 // Returns S_OK on success. | 124 IInternetProtocol* protocol_; |
| 205 static HRESULT PatchProtocolMethods( | 125 InternetProtocol_Read_Fn read_fun_; |
| 206 const CLSID& protocol_clsid, | |
| 207 vtable_patch::MethodPatchInfo* protocol_patch_info, | |
| 208 vtable_patch::MethodPatchInfo* protocol_ex_patch_info); | |
| 209 | 126 |
| 210 // WARNING: Don't use GURL variables here. Please see | 127 // What BINDSTATUS_MIMETYPEAVAILABLE and Co. tells us. |
| 211 // http://b/issue?id=2102171 for details. | 128 ScopedBstr suggested_mime_type_; |
| 129 // At least one of the following has been received: |
| 130 // BINDSTATUS_MIMETYPEAVAILABLE, |
| 131 // MIMESTATUS_VERIFIEDMIMETYPEAVAILABLE |
| 132 // BINDSTATUS_SERVER_MIMETYPEAVAILABLE |
| 133 bool has_suggested_mime_type_; |
| 134 // BINDSTATUS_SERVER_MIMETYPEAVAILABLE received, so we shall fire one. |
| 135 bool has_server_mime_type_; |
| 212 | 136 |
| 213 // Remember original sink | 137 // Did we received ReportData() |
| 214 ScopedComPtr<IInternetProtocolSink> delegate_; | 138 bool report_data_received_; |
| 215 | |
| 216 // Cannot take a reference on the protocol. | |
| 217 IInternetProtocol* protocol_; | |
| 218 RendererType renderer_type_; | 139 RendererType renderer_type_; |
| 219 | 140 |
| 220 // Buffer for accumulated data including 1 extra for NULL-terminator | 141 // Buffer for accumulated data including 1 extra for NULL-terminator |
| 142 static const size_t kMaxContentSniffLength = 2 * 1024; |
| 221 char buffer_[kMaxContentSniffLength + 1]; | 143 char buffer_[kMaxContentSniffLength + 1]; |
| 222 unsigned long buffer_size_; // NOLINT | 144 unsigned long buffer_size_; // NOLINT |
| 223 unsigned long buffer_pos_; // NOLINT | 145 unsigned long buffer_pos_; // NOLINT |
| 224 | 146 |
| 225 // Accumulated result | 147 HRESULT FillBuffer(); |
| 226 bool is_saved_result_; | 148 void SaveSuggestedMimeType(LPCWSTR status_text); |
| 227 HRESULT result_code_; | 149 void FireSugestedMimeType(IInternetProtocolSink* delegate); |
| 228 DWORD result_error_; | |
| 229 std::wstring result_text_; | |
| 230 // For tracking re-entrency and preventing duplicate Read()s from | |
| 231 // distorting the outcome of ReportData. | |
| 232 int report_data_recursiveness_; | |
| 233 | |
| 234 static ProtocolSinkMap sink_map_; | |
| 235 // TODO(joshia): Replace with Lock | |
| 236 static CComAutoCriticalSection sink_map_lock_; | |
| 237 | |
| 238 std::wstring url_; | |
| 239 | |
| 240 // Set to true if we are in the context of determining the desired renderer | |
| 241 // type. | |
| 242 bool determining_renderer_type_; | |
| 243 | |
| 244 private: | |
| 245 DISALLOW_COPY_AND_ASSIGN(ProtocolSinkWrap); | |
| 246 }; | 150 }; |
| 247 | 151 |
| 152 struct TransactionHooks { |
| 153 void InstallHooks(); |
| 154 void RevertHooks(); |
| 155 }; |
| 156 |
| 157 DECLSPEC_SELECTANY struct TransactionHooks g_trans_hooks; |
| 158 |
| 248 #endif // CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ | 159 #endif // CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ |
| 160 |
| OLD | NEW |