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.
5 #ifndef CHROME_FRAME_PROTOCOL_SINK_WRAP_H_
6 #define CHROME_FRAME_PROTOCOL_SINK_WRAP_H_
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"
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
,
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
);
49 // A class to wrap protocol sink in IInternetProtocol::Start[Ex] for
50 // HTTP and HTTPS protocols.
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.
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
{
64 BEGIN_COM_MAP(ProtocolSinkWrap
)
65 COM_INTERFACE_ENTRY(IInternetProtocolSink
)
66 COM_INTERFACE_BLIND_DELEGATE()
69 static base::win::ScopedComPtr
<IInternetProtocolSink
> CreateNewSink(
70 IInternetProtocolSink
* sink
, ProtData
* prot_data
);
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_
; }
77 // Apparently this has to be public, to satisfy COM_INTERFACE_BLIND_DELEGATE
78 IInternetProtocolSink
* delegate() {
87 static bool ignore_xua_
;
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
);
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
);
102 class ProtData
: public base::RefCounted
<ProtData
> {
104 ProtData(IInternetProtocol
* protocol
, InternetProtocol_Read_Fn read_fun
,
107 HRESULT
Read(void* buffer
, ULONG size
, ULONG
* size_read
);
108 HRESULT
ReportProgress(IInternetProtocolSink
* delegate
,
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
);
118 RendererType
renderer_type() {
119 return renderer_type_
;
122 // Valid only if renderer_type_ is CHROME.
123 const std::string
& referrer() const {
127 bool is_attach_external_tab_request() const {
128 return read_fun_
== NULL
;
131 // Removes the mapping between the protocol and the ProtData.
134 const std::wstring
& url() const {
139 typedef std::map
<IInternetProtocol
*, ProtData
*> ProtocolDataMap
;
140 static ProtocolDataMap datamap_
;
141 static base::Lock datamap_lock_
;
143 // Url we are retrieving. Used for RendererTypeForUrl() only.
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_
;
149 // Our gate to IInternetProtocol::Read()
150 IInternetProtocol
* protocol_
;
151 InternetProtocol_Read_Fn read_fun_
;
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_
;
163 RendererType renderer_type_
;
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
171 HRESULT
FillBuffer();
172 void SaveSuggestedMimeType(LPCWSTR status_text
);
173 void FireSuggestedMimeType(IInternetProtocolSink
* delegate
);
174 void SaveReferrer(IInternetProtocolSink
* delegate
);
177 struct TransactionHooks
{
182 DECLSPEC_SELECTANY
struct TransactionHooks g_trans_hooks
;
184 #endif // CHROME_FRAME_PROTOCOL_SINK_WRAP_H_