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 "googleurl/src/gurl.h"
21 #include "chrome_frame/chrome_frame_delegate.h"
22 #include "chrome_frame/http_negotiate.h"
23 #include "chrome_frame/ie8_types.h"
24 #include "chrome_frame/utils.h"
25 #include "chrome_frame/vtable_patch_manager.h"
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
,
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
);
39 typedef HRESULT (STDMETHODCALLTYPE
* InternetProtocol_LockRequest_Fn
)(
40 IInternetProtocol
* this_object
, DWORD options
);
41 typedef HRESULT (STDMETHODCALLTYPE
* InternetProtocol_UnlockRequest_Fn
)(
42 IInternetProtocol
* this_object
);
43 typedef HRESULT (STDMETHODCALLTYPE
* InternetProtocol_Abort_Fn
)(
44 IInternetProtocol
* this_object
, HRESULT hr
, DWORD options
);
45 typedef HRESULT (STDMETHODCALLTYPE
* InternetProtocol_Terminate_Fn
)(
46 IInternetProtocol
* this_object
, DWORD options
);
50 // A class to wrap protocol sink in IInternetProtocol::Start[Ex] for
51 // HTTP and HTTPS protocols.
53 // This is an alternative to a mime filter and we have to do this in order
54 // to inspect initial portion of HTML for 'chrome' meta tag and report
55 // a different mime type in that case.
57 // We implement several documented interfaces
58 // supported by the original sink provided by urlmon. There are a few
59 // undocumented interfaces that we have chosen not to implement
60 // but delegate simply the QI.
61 class ProtocolSinkWrap
62 : public CComObjectRootEx
<CComMultiThreadModel
>,
63 public IInternetProtocolSink
{
66 BEGIN_COM_MAP(ProtocolSinkWrap
)
67 COM_INTERFACE_ENTRY(IInternetProtocolSink
)
68 COM_INTERFACE_BLIND_DELEGATE()
71 static base::win::ScopedComPtr
<IInternetProtocolSink
> CreateNewSink(
72 IInternetProtocolSink
* sink
, ProtData
* prot_data
);
74 // Enables or disables activation of Chrome Frame via the X-UA-Compatible
75 // header or meta tag. The tag/header is respected by default.
76 static void set_ignore_xua(bool ignore_xua
) { ignore_xua_
= ignore_xua
; }
77 static bool ignore_xua() { return ignore_xua_
; }
79 // Apparently this has to be public, to satisfy COM_INTERFACE_BLIND_DELEGATE
80 IInternetProtocolSink
* delegate() {
89 static bool ignore_xua_
;
91 // IInternetProtocolSink methods
92 STDMETHOD(Switch
)(PROTOCOLDATA
* protocol_data
);
93 STDMETHOD(ReportProgress
)(ULONG status_code
, LPCWSTR status_text
);
94 STDMETHOD(ReportData
)(DWORD flags
, ULONG progress
, ULONG max_progress
);
95 STDMETHOD(ReportResult
)(HRESULT result
, DWORD error
, LPCWSTR result_text
);
97 // Remember original sink
98 base::win::ScopedComPtr
<IInternetProtocolSink
> delegate_
;
99 base::win::ScopedComPtr
<IServiceProvider
> delegate_service_provider_
;
100 scoped_refptr
<ProtData
> prot_data_
;
101 DISALLOW_COPY_AND_ASSIGN(ProtocolSinkWrap
);
104 class ProtData
: public base::RefCounted
<ProtData
> {
106 ProtData(IInternetProtocol
* protocol
, InternetProtocol_Read_Fn read_fun
,
109 HRESULT
Read(void* buffer
, ULONG size
, ULONG
* size_read
);
110 HRESULT
ReportProgress(IInternetProtocolSink
* delegate
,
112 LPCWSTR status_text
);
113 HRESULT
ReportData(IInternetProtocolSink
* delegate
,
114 DWORD flags
, ULONG progress
, ULONG max_progress
);
115 HRESULT
ReportResult(IInternetProtocolSink
* delegate
, HRESULT result
,
116 DWORD error
, LPCWSTR result_text
);
117 void UpdateUrl(const wchar_t* url
);
118 static scoped_refptr
<ProtData
> DataFromProtocol(IInternetProtocol
* protocol
);
120 RendererType
renderer_type() {
121 return renderer_type_
;
124 // Valid only if renderer_type_ is CHROME.
125 const std::string
& referrer() const {
129 bool is_attach_external_tab_request() const {
130 return read_fun_
== NULL
;
133 // Removes the mapping between the protocol and the ProtData.
136 const std::wstring
& url() const {
141 typedef std::map
<IInternetProtocol
*, ProtData
*> ProtocolDataMap
;
142 static ProtocolDataMap datamap_
;
143 static base::Lock datamap_lock_
;
145 // Url we are retrieving. Used for RendererTypeForUrl() only.
147 // HTTP "Referrer" header if we detect are going to switch.
148 // We have to save and pass it to Chrome, so scripts can read it via DOM.
149 std::string referrer_
;
151 // Our gate to IInternetProtocol::Read()
152 IInternetProtocol
* protocol_
;
153 InternetProtocol_Read_Fn read_fun_
;
155 // What BINDSTATUS_MIMETYPEAVAILABLE and Co. tells us.
156 base::win::ScopedBstr suggested_mime_type_
;
157 // At least one of the following has been received:
158 // BINDSTATUS_MIMETYPEAVAILABLE,
159 // MIMESTATUS_VERIFIEDMIMETYPEAVAILABLE
160 // BINDSTATUS_SERVER_MIMETYPEAVAILABLE
161 bool has_suggested_mime_type_
;
162 // BINDSTATUS_SERVER_MIMETYPEAVAILABLE received, so we shall fire one.
163 bool has_server_mime_type_
;
165 RendererType renderer_type_
;
167 // Buffer for accumulated data including 1 extra for NULL-terminator
168 static const size_t kMaxContentSniffLength
= 2 * 1024;
169 char buffer_
[kMaxContentSniffLength
+ 1];
170 unsigned long buffer_size_
; // NOLINT
171 unsigned long buffer_pos_
; // NOLINT
173 HRESULT
FillBuffer();
174 void SaveSuggestedMimeType(LPCWSTR status_text
);
175 void FireSuggestedMimeType(IInternetProtocolSink
* delegate
);
176 void SaveReferrer(IInternetProtocolSink
* delegate
);
179 struct TransactionHooks
{
184 DECLSPEC_SELECTANY
struct TransactionHooks g_trans_hooks
;
186 #endif // CHROME_FRAME_PROTOCOL_SINK_WRAP_H_