[email protected] | 6e58a95 | 2011-01-12 19:28:50 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ |
| 6 | #define CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ |
| 7 | |
| 8 | #include <exdisp.h> |
| 9 | #include <urlmon.h> |
| 10 | #include <atlbase.h> |
| 11 | #include <atlcom.h> |
[email protected] | 3f55e87 | 2009-10-17 04:48:37 | [diff] [blame] | 12 | |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 13 | #include <map> |
| 14 | #include <string> |
| 15 | |
| 16 | #include "base/basictypes.h" |
[email protected] | 3b63f8f4 | 2011-03-28 01:54:15 | [diff] [blame] | 17 | #include "base/memory/ref_counted.h" |
[email protected] | 965722ff | 2010-10-20 15:50:30 | [diff] [blame] | 18 | #include "base/win/scoped_comptr.h" |
| 19 | #include "base/win/scoped_bstr.h" |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 20 | #include "googleurl/src/gurl.h" |
[email protected] | 921a31d | 2009-12-23 19:43:12 | [diff] [blame] | 21 | #include "chrome_frame/chrome_frame_delegate.h" |
[email protected] | aaf12450 | 2010-07-17 04:02:58 | [diff] [blame] | 22 | #include "chrome_frame/http_negotiate.h" |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 23 | #include "chrome_frame/ie8_types.h" |
[email protected] | 3f55e87 | 2009-10-17 04:48:37 | [diff] [blame] | 24 | #include "chrome_frame/utils.h" |
[email protected] | bc88e9d7 | 2009-09-25 16:04:43 | [diff] [blame] | 25 | #include "chrome_frame/vtable_patch_manager.h" |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 26 | |
| 27 | // Typedefs for IInternetProtocol and related methods that we patch. |
| 28 | typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Start_Fn)( |
| 29 | IInternetProtocol* this_object, LPCWSTR url, |
| 30 | IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, |
| 31 | DWORD flags, HANDLE_PTR reserved); |
| 32 | typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Read_Fn)( |
| 33 | IInternetProtocol* this_object, void* buffer, ULONG size, |
| 34 | ULONG* size_read); |
| 35 | typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_StartEx_Fn)( |
| 36 | IInternetProtocolEx* this_object, IUri* uri, |
| 37 | IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info, |
| 38 | DWORD flags, HANDLE_PTR reserved); |
[email protected] | c4e45b3 | 2010-07-28 21:15:15 | [diff] [blame] | 39 | typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_LockRequest_Fn)( |
| 40 | IInternetProtocol* this_object, DWORD options); |
| 41 | typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_UnlockRequest_Fn)( |
| 42 | IInternetProtocol* this_object); |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 43 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 44 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 45 | class ProtData; |
| 46 | |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 47 | // A class to wrap protocol sink in IInternetProtocol::Start[Ex] for |
| 48 | // HTTP and HTTPS protocols. |
| 49 | // |
| 50 | // This is an alternative to a mime filter and we have to do this in order |
| 51 | // to inspect initial portion of HTML for 'chrome' meta tag and report |
| 52 | // a different mime type in that case. |
| 53 | // |
| 54 | // We implement several documented interfaces |
| 55 | // supported by the original sink provided by urlmon. There are a few |
| 56 | // undocumented interfaces that we have chosen not to implement |
| 57 | // but delegate simply the QI. |
| 58 | class ProtocolSinkWrap |
| 59 | : public CComObjectRootEx<CComMultiThreadModel>, |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 60 | public IInternetProtocolSink { |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 61 | public: |
| 62 | |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 63 | BEGIN_COM_MAP(ProtocolSinkWrap) |
| 64 | COM_INTERFACE_ENTRY(IInternetProtocolSink) |
[email protected] | 3f55e87 | 2009-10-17 04:48:37 | [diff] [blame] | 65 | COM_INTERFACE_BLIND_DELEGATE() |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 66 | END_COM_MAP() |
| 67 | |
[email protected] | 965722ff | 2010-10-20 15:50:30 | [diff] [blame] | 68 | static base::win::ScopedComPtr<IInternetProtocolSink> CreateNewSink( |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 69 | IInternetProtocolSink* sink, ProtData* prot_data); |
| 70 | |
[email protected] | 6e58a95 | 2011-01-12 19:28:50 | [diff] [blame] | 71 | // Enables or disables activation of Chrome Frame via the X-UA-Compatible |
| 72 | // header or meta tag. The tag/header is respected by default. |
| 73 | static void set_ignore_xua(bool ignore_xua) { ignore_xua_ = ignore_xua; } |
| 74 | static bool ignore_xua() { return ignore_xua_; } |
| 75 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 76 | // Apparently this has to be public, to satisfy COM_INTERFACE_BLIND_DELEGATE |
| 77 | IInternetProtocolSink* delegate() { |
| 78 | return delegate_; |
| 79 | } |
| 80 | |
| 81 | protected: |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 82 | ProtocolSinkWrap(); |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 83 | ~ProtocolSinkWrap(); |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 84 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 85 | private: |
[email protected] | 6e58a95 | 2011-01-12 19:28:50 | [diff] [blame] | 86 | static bool ignore_xua_; |
| 87 | |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 88 | // IInternetProtocolSink methods |
| 89 | STDMETHOD(Switch)(PROTOCOLDATA* protocol_data); |
| 90 | STDMETHOD(ReportProgress)(ULONG status_code, LPCWSTR status_text); |
| 91 | STDMETHOD(ReportData)(DWORD flags, ULONG progress, ULONG max_progress); |
| 92 | STDMETHOD(ReportResult)(HRESULT result, DWORD error, LPCWSTR result_text); |
| 93 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 94 | // Remember original sink |
[email protected] | 965722ff | 2010-10-20 15:50:30 | [diff] [blame] | 95 | base::win::ScopedComPtr<IInternetProtocolSink> delegate_; |
| 96 | base::win::ScopedComPtr<IServiceProvider> delegate_service_provider_; |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 97 | scoped_refptr<ProtData> prot_data_; |
| 98 | DISALLOW_COPY_AND_ASSIGN(ProtocolSinkWrap); |
| 99 | }; |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 100 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 101 | class ProtData : public base::RefCounted<ProtData> { |
| 102 | public: |
| 103 | ProtData(IInternetProtocol* protocol, InternetProtocol_Read_Fn read_fun, |
| 104 | const wchar_t* url); |
| 105 | ~ProtData(); |
| 106 | HRESULT Read(void* buffer, ULONG size, ULONG* size_read); |
| 107 | HRESULT ReportProgress(IInternetProtocolSink* delegate, |
| 108 | ULONG status_code, |
| 109 | LPCWSTR status_text); |
| 110 | HRESULT ReportData(IInternetProtocolSink* delegate, |
| 111 | DWORD flags, ULONG progress, ULONG max_progress); |
| 112 | HRESULT ReportResult(IInternetProtocolSink* delegate, HRESULT result, |
| 113 | DWORD error, LPCWSTR result_text); |
| 114 | void UpdateUrl(const wchar_t* url); |
| 115 | static scoped_refptr<ProtData> DataFromProtocol(IInternetProtocol* protocol); |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 116 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 117 | RendererType renderer_type() { |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 118 | return renderer_type_; |
| 119 | } |
| 120 | |
[email protected] | aaf12450 | 2010-07-17 04:02:58 | [diff] [blame] | 121 | // Valid only if renderer_type_ is CHROME. |
| 122 | const std::string& referrer() const { |
| 123 | return referrer_; |
| 124 | } |
| 125 | |
[email protected] | c4e45b3 | 2010-07-28 21:15:15 | [diff] [blame] | 126 | bool is_attach_external_tab_request() const { |
| 127 | return read_fun_ == NULL; |
| 128 | } |
| 129 | |
[email protected] | 5aef0fa | 2010-08-02 17:10:57 | [diff] [blame] | 130 | // Removes the mapping between the protocol and the ProtData. |
| 131 | void Invalidate(); |
| 132 | |
[email protected] | 4f45d458 | 2011-02-22 23:27:27 | [diff] [blame] | 133 | const std::wstring& url() const { |
| 134 | return url_; |
| 135 | } |
| 136 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 137 | private: |
| 138 | typedef std::map<IInternetProtocol*, ProtData*> ProtocolDataMap; |
| 139 | static ProtocolDataMap datamap_; |
[email protected] | 68c3403 | 2011-01-21 05:30:19 | [diff] [blame] | 140 | static base::Lock datamap_lock_; |
[email protected] | bc88e9d7 | 2009-09-25 16:04:43 | [diff] [blame] | 141 | |
[email protected] | d8e1351 | 2010-09-22 17:02:58 | [diff] [blame] | 142 | // Url we are retrieving. Used for RendererTypeForUrl() only. |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 143 | std::wstring url_; |
[email protected] | aaf12450 | 2010-07-17 04:02:58 | [diff] [blame] | 144 | // HTTP "Referrer" header if we detect are going to switch. |
| 145 | // We have to save and pass it to Chrome, so scripts can read it via DOM. |
| 146 | std::string referrer_; |
| 147 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 148 | // Our gate to IInternetProtocol::Read() |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 149 | IInternetProtocol* protocol_; |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 150 | InternetProtocol_Read_Fn read_fun_; |
| 151 | |
| 152 | // What BINDSTATUS_MIMETYPEAVAILABLE and Co. tells us. |
[email protected] | 965722ff | 2010-10-20 15:50:30 | [diff] [blame] | 153 | base::win::ScopedBstr suggested_mime_type_; |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 154 | // At least one of the following has been received: |
| 155 | // BINDSTATUS_MIMETYPEAVAILABLE, |
| 156 | // MIMESTATUS_VERIFIEDMIMETYPEAVAILABLE |
| 157 | // BINDSTATUS_SERVER_MIMETYPEAVAILABLE |
| 158 | bool has_suggested_mime_type_; |
| 159 | // BINDSTATUS_SERVER_MIMETYPEAVAILABLE received, so we shall fire one. |
| 160 | bool has_server_mime_type_; |
| 161 | |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 162 | RendererType renderer_type_; |
| 163 | |
| 164 | // Buffer for accumulated data including 1 extra for NULL-terminator |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 165 | static const size_t kMaxContentSniffLength = 2 * 1024; |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 166 | char buffer_[kMaxContentSniffLength + 1]; |
[email protected] | 3f55e87 | 2009-10-17 04:48:37 | [diff] [blame] | 167 | unsigned long buffer_size_; // NOLINT |
| 168 | unsigned long buffer_pos_; // NOLINT |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 169 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 170 | HRESULT FillBuffer(); |
| 171 | void SaveSuggestedMimeType(LPCWSTR status_text); |
[email protected] | 7ab36c4f | 2010-08-11 03:47:43 | [diff] [blame] | 172 | void FireSuggestedMimeType(IInternetProtocolSink* delegate); |
[email protected] | aaf12450 | 2010-07-17 04:02:58 | [diff] [blame] | 173 | void SaveReferrer(IInternetProtocolSink* delegate); |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 174 | }; |
| 175 | |
[email protected] | ce2b9f92 | 2010-06-09 16:54:12 | [diff] [blame] | 176 | struct TransactionHooks { |
| 177 | void InstallHooks(); |
| 178 | void RevertHooks(); |
| 179 | }; |
| 180 | |
| 181 | DECLSPEC_SELECTANY struct TransactionHooks g_trans_hooks; |
| 182 | |
[email protected] | f781782 | 2009-09-24 05:11:58 | [diff] [blame] | 183 | #endif // CHROME_FRAME_PROTOCOL_SINK_WRAP_H_ |