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