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
);
47 // A class to wrap protocol sink in IInternetProtocol::Start[Ex] for
48 // HTTP and HTTPS protocols.
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.
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
>,
60 public IInternetProtocolSink
{
63 BEGIN_COM_MAP(ProtocolSinkWrap
)
64 COM_INTERFACE_ENTRY(IInternetProtocolSink
)
65 COM_INTERFACE_BLIND_DELEGATE()
68 static base::win::ScopedComPtr
<IInternetProtocolSink
> CreateNewSink(
69 IInternetProtocolSink
* sink
, ProtData
* prot_data
);
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_
; }
76 // Apparently this has to be public, to satisfy COM_INTERFACE_BLIND_DELEGATE
77 IInternetProtocolSink
* delegate() {
86 static bool ignore_xua_
;
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
);
94 // Remember original sink
95 base::win::ScopedComPtr
<IInternetProtocolSink
> delegate_
;
96 base::win::ScopedComPtr
<IServiceProvider
> delegate_service_provider_
;
97 scoped_refptr
<ProtData
> prot_data_
;
98 DISALLOW_COPY_AND_ASSIGN(ProtocolSinkWrap
);
101 class ProtData
: public base::RefCounted
<ProtData
> {
103 ProtData(IInternetProtocol
* protocol
, InternetProtocol_Read_Fn read_fun
,
106 HRESULT
Read(void* buffer
, ULONG size
, ULONG
* size_read
);
107 HRESULT
ReportProgress(IInternetProtocolSink
* delegate
,
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
);
117 RendererType
renderer_type() {
118 return renderer_type_
;
121 // Valid only if renderer_type_ is CHROME.
122 const std::string
& referrer() const {
126 bool is_attach_external_tab_request() const {
127 return read_fun_
== NULL
;
130 // Removes the mapping between the protocol and the ProtData.
133 const std::wstring
& url() const {
138 typedef std::map
<IInternetProtocol
*, ProtData
*> ProtocolDataMap
;
139 static ProtocolDataMap datamap_
;
140 static base::Lock datamap_lock_
;
142 // Url we are retrieving. Used for RendererTypeForUrl() only.
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_
;
148 // Our gate to IInternetProtocol::Read()
149 IInternetProtocol
* protocol_
;
150 InternetProtocol_Read_Fn read_fun_
;
152 // What BINDSTATUS_MIMETYPEAVAILABLE and Co. tells us.
153 base::win::ScopedBstr suggested_mime_type_
;
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_
;
162 RendererType renderer_type_
;
164 // Buffer for accumulated data including 1 extra for NULL-terminator
165 static const size_t kMaxContentSniffLength
= 2 * 1024;
166 char buffer_
[kMaxContentSniffLength
+ 1];
167 unsigned long buffer_size_
; // NOLINT
168 unsigned long buffer_pos_
; // NOLINT
170 HRESULT
FillBuffer();
171 void SaveSuggestedMimeType(LPCWSTR status_text
);
172 void FireSuggestedMimeType(IInternetProtocolSink
* delegate
);
173 void SaveReferrer(IInternetProtocolSink
* delegate
);
176 struct TransactionHooks
{
181 DECLSPEC_SELECTANY
struct TransactionHooks g_trans_hooks
;
183 #endif // CHROME_FRAME_PROTOCOL_SINK_WRAP_H_