blob: c5dc4610bb028ef09c2736519e2897f9e78285e5 [file] [log] [blame]
[email protected]6e58a952011-01-12 19:28:501// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]f7817822009-09-24 05:11:582// 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]3f55e872009-10-17 04:48:3712
[email protected]f7817822009-09-24 05:11:5813#include <map>
14#include <string>
15
16#include "base/basictypes.h"
[email protected]3b63f8f42011-03-28 01:54:1517#include "base/memory/ref_counted.h"
[email protected]965722ff2010-10-20 15:50:3018#include "base/win/scoped_comptr.h"
19#include "base/win/scoped_bstr.h"
[email protected]f7817822009-09-24 05:11:5820#include "googleurl/src/gurl.h"
[email protected]921a31d2009-12-23 19:43:1221#include "chrome_frame/chrome_frame_delegate.h"
[email protected]aaf124502010-07-17 04:02:5822#include "chrome_frame/http_negotiate.h"
[email protected]f7817822009-09-24 05:11:5823#include "chrome_frame/ie8_types.h"
[email protected]3f55e872009-10-17 04:48:3724#include "chrome_frame/utils.h"
[email protected]bc88e9d72009-09-25 16:04:4325#include "chrome_frame/vtable_patch_manager.h"
[email protected]f7817822009-09-24 05:11:5826
27// Typedefs for IInternetProtocol and related methods that we patch.
28typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Start_Fn)(
29 IInternetProtocol* this_object, LPCWSTR url,
30 IInternetProtocolSink* prot_sink, IInternetBindInfo* bind_info,
31 DWORD flags, HANDLE_PTR reserved);
32typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Read_Fn)(
33 IInternetProtocol* this_object, void* buffer, ULONG size,
34 ULONG* size_read);
35typedef 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]c4e45b32010-07-28 21:15:1539typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_LockRequest_Fn)(
40 IInternetProtocol* this_object, DWORD options);
41typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_UnlockRequest_Fn)(
42 IInternetProtocol* this_object);
[email protected]bb7097f2013-01-31 19:54:3243typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Abort_Fn)(
44 IInternetProtocol* this_object, HRESULT hr, DWORD options);
45typedef HRESULT (STDMETHODCALLTYPE* InternetProtocol_Terminate_Fn)(
46 IInternetProtocol* this_object, DWORD options);
[email protected]ce2b9f922010-06-09 16:54:1247
[email protected]ce2b9f922010-06-09 16:54:1248class ProtData;
49
[email protected]f7817822009-09-24 05:11:5850// A class to wrap protocol sink in IInternetProtocol::Start[Ex] for
51// HTTP and HTTPS protocols.
52//
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.
56//
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.
61class ProtocolSinkWrap
62 : public CComObjectRootEx<CComMultiThreadModel>,
[email protected]ce2b9f922010-06-09 16:54:1263 public IInternetProtocolSink {
[email protected]f7817822009-09-24 05:11:5864 public:
65
[email protected]f7817822009-09-24 05:11:5866BEGIN_COM_MAP(ProtocolSinkWrap)
67 COM_INTERFACE_ENTRY(IInternetProtocolSink)
[email protected]3f55e872009-10-17 04:48:3768 COM_INTERFACE_BLIND_DELEGATE()
[email protected]f7817822009-09-24 05:11:5869END_COM_MAP()
70
[email protected]965722ff2010-10-20 15:50:3071 static base::win::ScopedComPtr<IInternetProtocolSink> CreateNewSink(
[email protected]ce2b9f922010-06-09 16:54:1272 IInternetProtocolSink* sink, ProtData* prot_data);
73
[email protected]6e58a952011-01-12 19:28:5074 // 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_; }
78
[email protected]ce2b9f922010-06-09 16:54:1279 // Apparently this has to be public, to satisfy COM_INTERFACE_BLIND_DELEGATE
80 IInternetProtocolSink* delegate() {
81 return delegate_;
82 }
83
84 protected:
[email protected]f7817822009-09-24 05:11:5885 ProtocolSinkWrap();
[email protected]ce2b9f922010-06-09 16:54:1286 ~ProtocolSinkWrap();
[email protected]f7817822009-09-24 05:11:5887
[email protected]ce2b9f922010-06-09 16:54:1288 private:
[email protected]6e58a952011-01-12 19:28:5089 static bool ignore_xua_;
90
[email protected]f7817822009-09-24 05:11:5891 // 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);
96
[email protected]ce2b9f922010-06-09 16:54:1297 // Remember original sink
[email protected]965722ff2010-10-20 15:50:3098 base::win::ScopedComPtr<IInternetProtocolSink> delegate_;
99 base::win::ScopedComPtr<IServiceProvider> delegate_service_provider_;
[email protected]ce2b9f922010-06-09 16:54:12100 scoped_refptr<ProtData> prot_data_;
101 DISALLOW_COPY_AND_ASSIGN(ProtocolSinkWrap);
102};
[email protected]f7817822009-09-24 05:11:58103
[email protected]ce2b9f922010-06-09 16:54:12104class ProtData : public base::RefCounted<ProtData> {
105 public:
106 ProtData(IInternetProtocol* protocol, InternetProtocol_Read_Fn read_fun,
107 const wchar_t* url);
108 ~ProtData();
109 HRESULT Read(void* buffer, ULONG size, ULONG* size_read);
110 HRESULT ReportProgress(IInternetProtocolSink* delegate,
111 ULONG status_code,
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);
[email protected]f7817822009-09-24 05:11:58119
[email protected]ce2b9f922010-06-09 16:54:12120 RendererType renderer_type() {
[email protected]f7817822009-09-24 05:11:58121 return renderer_type_;
122 }
123
[email protected]aaf124502010-07-17 04:02:58124 // Valid only if renderer_type_ is CHROME.
125 const std::string& referrer() const {
126 return referrer_;
127 }
128
[email protected]c4e45b32010-07-28 21:15:15129 bool is_attach_external_tab_request() const {
130 return read_fun_ == NULL;
131 }
132
[email protected]5aef0fa2010-08-02 17:10:57133 // Removes the mapping between the protocol and the ProtData.
134 void Invalidate();
135
[email protected]4f45d4582011-02-22 23:27:27136 const std::wstring& url() const {
137 return url_;
138 }
139
[email protected]ce2b9f922010-06-09 16:54:12140 private:
141 typedef std::map<IInternetProtocol*, ProtData*> ProtocolDataMap;
142 static ProtocolDataMap datamap_;
[email protected]68c34032011-01-21 05:30:19143 static base::Lock datamap_lock_;
[email protected]bc88e9d72009-09-25 16:04:43144
[email protected]d8e13512010-09-22 17:02:58145 // Url we are retrieving. Used for RendererTypeForUrl() only.
[email protected]ce2b9f922010-06-09 16:54:12146 std::wstring url_;
[email protected]aaf124502010-07-17 04:02:58147 // 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_;
150
[email protected]ce2b9f922010-06-09 16:54:12151 // Our gate to IInternetProtocol::Read()
[email protected]f7817822009-09-24 05:11:58152 IInternetProtocol* protocol_;
[email protected]ce2b9f922010-06-09 16:54:12153 InternetProtocol_Read_Fn read_fun_;
154
155 // What BINDSTATUS_MIMETYPEAVAILABLE and Co. tells us.
[email protected]965722ff2010-10-20 15:50:30156 base::win::ScopedBstr suggested_mime_type_;
[email protected]ce2b9f922010-06-09 16:54:12157 // 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_;
164
[email protected]f7817822009-09-24 05:11:58165 RendererType renderer_type_;
166
167 // Buffer for accumulated data including 1 extra for NULL-terminator
[email protected]ce2b9f922010-06-09 16:54:12168 static const size_t kMaxContentSniffLength = 2 * 1024;
[email protected]f7817822009-09-24 05:11:58169 char buffer_[kMaxContentSniffLength + 1];
[email protected]3f55e872009-10-17 04:48:37170 unsigned long buffer_size_; // NOLINT
171 unsigned long buffer_pos_; // NOLINT
[email protected]f7817822009-09-24 05:11:58172
[email protected]ce2b9f922010-06-09 16:54:12173 HRESULT FillBuffer();
174 void SaveSuggestedMimeType(LPCWSTR status_text);
[email protected]7ab36c4f2010-08-11 03:47:43175 void FireSuggestedMimeType(IInternetProtocolSink* delegate);
[email protected]aaf124502010-07-17 04:02:58176 void SaveReferrer(IInternetProtocolSink* delegate);
[email protected]f7817822009-09-24 05:11:58177};
178
[email protected]ce2b9f922010-06-09 16:54:12179struct TransactionHooks {
180 void InstallHooks();
181 void RevertHooks();
182};
183
184DECLSPEC_SELECTANY struct TransactionHooks g_trans_hooks;
185
[email protected]f7817822009-09-24 05:11:58186#endif // CHROME_FRAME_PROTOCOL_SINK_WRAP_H_