Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: src/plugin/PluginWbPassThrough.cpp

Issue 5171515343503360: Issue #41 - Bring method of determining IE version up to date (Closed)
Left Patch Set: Created July 29, 2014, 2:45 p.m.
Right Patch Set: Final (?) 2 Created Jan. 5, 2015, 1:02 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
1 #include "PluginStdAfx.h" 1 #include "PluginStdAfx.h"
2 2
3 #include "PluginWbPassThrough.h" 3 #include "PluginWbPassThrough.h"
4 #include "PluginClient.h" 4 #include "PluginClient.h"
5 #include "PluginClientFactory.h" 5 #include "PluginClientFactory.h"
6 #ifdef SUPPORT_FILTER
7 #include "PluginFilter.h" 6 #include "PluginFilter.h"
8 #endif
9 #include "PluginSettings.h" 7 #include "PluginSettings.h"
10 #include "PluginClass.h" 8 #include "PluginClass.h"
11 #include "PluginSystem.h" 9 #include "PluginSystem.h"
10 #include <WinInet.h>
11 #include "wtypes.h"
12 #include "../shared/Utils.h"
12 #include "../shared/IE_version.h" 13 #include "../shared/IE_version.h"
13 #include "wtypes.h" 14
14 15 namespace
15 EXTERN_C IMAGE_DOS_HEADER __ImageBase; 16 {
16 17 const std::string g_blockedByABPPage = "<!DOCTYPE html>"
17 18 "<html>"
18 19 "<body>"
19 int WBPassthruSink::GetContentTypeFromMimeType(CString mimeType) 20 "<!-- blocked by AdblockPlus -->"
21 "</body>"
22 "</html>";
23
24 template <class T>
25 T ExtractHttpHeader(const T& allHeaders, const T& targetHeaderNameWithColon, c onst T& delimiter)
26 {
27 auto targetHeaderBeginsAt = allHeaders.find(targetHeaderNameWithColon);
28 if (targetHeaderBeginsAt == T::npos)
29 {
30 return T();
31 }
32 targetHeaderBeginsAt += targetHeaderNameWithColon.length();
33 auto targetHeaderEndsAt = allHeaders.find(delimiter, targetHeaderBeginsAt);
34 if (targetHeaderEndsAt == T::npos)
35 {
36 return T();
37 }
38 return allHeaders.substr(targetHeaderBeginsAt, targetHeaderEndsAt - targetHe aderBeginsAt);
39 }
40
41 std::string ExtractHttpAcceptHeader(IInternetProtocol* internetProtocol)
42 {
43 // Despite there being HTTP_QUERY_ACCEPT and other query info flags, they do n't work here,
44 // only HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS does w ork.
45 ATL::CComPtr<IWinInetHttpInfo> winInetHttpInfo;
46 HRESULT hr = internetProtocol->QueryInterface(&winInetHttpInfo);
47 if (FAILED(hr) || !winInetHttpInfo)
48 {
49 return "";
50 }
51 DWORD size = 0;
52 DWORD flags = 0;
53 DWORD queryOption = HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HE ADERS;
54 hr = winInetHttpInfo->QueryInfo(queryOption, /*buffer*/ nullptr, /*get size* / &size, &flags, /*reserved*/ 0);
55 if (FAILED(hr))
56 {
57 return "";
58 }
59 std::string buf(size, '\0');
60 hr = winInetHttpInfo->QueryInfo(queryOption, &buf[0], &size, &flags, 0);
61 if (FAILED(hr))
62 {
63 return "";
64 }
65 return ExtractHttpHeader<std::string>(buf, "Accept:", "\r\n");
66 }
67
68 bool IsXmlHttpRequest(const std::wstring& additionalHeaders)
69 {
70 auto requestedWithHeader = ExtractHttpHeader<std::wstring>(additionalHeaders , L"X-Requested-With:", L"\n");
71 return TrimString(requestedWithHeader) == L"XMLHttpRequest";
72 }
73 }
74
75 WBPassthruSink::WBPassthruSink()
76 : m_currentPositionOfSentPage(0)
77 , m_contentType(CFilter::EContentType::contentTypeAny)
78 , m_isCustomResponse(false)
79 {
80 }
81
82 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType)
20 { 83 {
21 if (mimeType.Find(L"image/") >= 0) 84 if (mimeType.Find(L"image/") >= 0)
22 { 85 {
23 return CFilter::contentTypeImage; 86 return CFilter::contentTypeImage;
24 } 87 }
25 if (mimeType.Find(L"text/css") >= 0) 88 if (mimeType.Find(L"text/css") >= 0)
26 { 89 {
27 return CFilter::contentTypeStyleSheet; 90 return CFilter::contentTypeStyleSheet;
28 } 91 }
29 if ((mimeType.Find(L"application/javascript") >= 0) || (mimeType.Find(L"applic ation/json") >= 0)) 92 if ((mimeType.Find(L"application/javascript") >= 0) || (mimeType.Find(L"applic ation/json") >= 0))
(...skipping 10 matching lines...) Expand all
40 } 103 }
41 // It is important to have this check last, since it is rather generic, and mi ght overlay text/html, for example 104 // It is important to have this check last, since it is rather generic, and mi ght overlay text/html, for example
42 if (mimeType.Find(L"xml") >= 0) 105 if (mimeType.Find(L"xml") >= 0)
43 { 106 {
44 return CFilter::contentTypeXmlHttpRequest; 107 return CFilter::contentTypeXmlHttpRequest;
45 } 108 }
46 109
47 return CFilter::contentTypeAny; 110 return CFilter::contentTypeAny;
48 } 111 }
49 112
50 int WBPassthruSink::GetContentTypeFromURL(CString src) 113 int WBPassthruSink::GetContentTypeFromURL(const CString& src)
51 { 114 {
52 CString srcExt = src; 115 CString srcExt = src;
53 116
54 int pos = 0; 117 int pos = 0;
55 if ((pos = src.Find('?')) > 0) 118 if ((pos = src.Find('?')) > 0)
56 { 119 {
57 srcExt = src.Left(pos); 120 srcExt = src.Left(pos);
58 } 121 }
59 122
60 int lastDotIndex = srcExt.ReverseFind('.'); 123 int lastDotIndex = srcExt.ReverseFind('.');
(...skipping 17 matching lines...) Expand all
78 return CFilter::contentTypeXmlHttpRequest; 141 return CFilter::contentTypeXmlHttpRequest;
79 } 142 }
80 else if (ext == L".swf") 143 else if (ext == L".swf")
81 { 144 {
82 return CFilter::contentTypeObject; 145 return CFilter::contentTypeObject;
83 } 146 }
84 else if (ext == L".jsp" || ext == L".php" || ext == L".html") 147 else if (ext == L".jsp" || ext == L".php" || ext == L".html")
85 { 148 {
86 return CFilter::contentTypeSubdocument; 149 return CFilter::contentTypeSubdocument;
87 } 150 }
88 else 151 return CFilter::contentTypeAny;
89 { 152 }
90 return CFilter::contentTypeAny & ~CFilter::contentTypeSubdocument; 153
91 } 154 int WBPassthruSink::GetContentType(const CString& mimeType, const std::wstring& domain, const CString& src)
92
93 }
94
95 int WBPassthruSink::GetContentType(CString mimeType, CString domain, CString src )
96 { 155 {
97 // No referer or mime type 156 // No referer or mime type
98 // BINDSTRING_XDR_ORIGIN works only for IE v8+ 157 // BINDSTRING_XDR_ORIGIN works only for IE v8+
99 if (mimeType.IsEmpty() && domain.IsEmpty() && AdblockPlus::IE::InstalledMajorV ersion() >= 8) 158 if (mimeType.IsEmpty() && domain.empty() && AdblockPlus::IE::InstalledMajorVer sion() >= 8)
sergei 2015/01/06 13:39:11 Actually we are supporting only versions starting
Eric 2015/01/06 17:10:34 You and Oleksandr and I had a discussion about thi
100 { 159 {
101 return CFilter::contentTypeXmlHttpRequest; 160 return CFilter::contentTypeXmlHttpRequest;
102 } 161 }
103 int contentType = GetContentTypeFromMimeType(mimeType); 162 int contentType = GetContentTypeFromMimeType(mimeType);
104 if (contentType == CFilter::contentTypeAny) 163 if (contentType == CFilter::contentTypeAny)
105 { 164 {
106 contentType = GetContentTypeFromURL(src); 165 contentType = GetContentTypeFromURL(src);
107 } 166 }
108 return contentType; 167 return contentType;
109 } 168 }
110 169
111 //////////////////////////////////////////////////////////////////////////////// //////// 170 //////////////////////////////////////////////////////////////////////////////// ////////
112 //WBPassthruSink 171 //WBPassthruSink
113 //Monitor and/or cancel every request and responde 172 //Monitor and/or cancel every request and responde
114 //WB makes, including images, sounds, scripts, etc 173 //WB makes, including images, sounds, scripts, etc
115 //////////////////////////////////////////////////////////////////////////////// //////// 174 //////////////////////////////////////////////////////////////////////////////// ////////
116 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k, 175 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k,
117 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN DLE_PTR dwReserved, 176 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN DLE_PTR dwReserved,
118 IInternetProtocol* pTargetProtocol) 177 IInternetProtocol* pTargetProtocol, bool& handle d)
119 { 178 {
120
121 m_pTargetProtocol = pTargetProtocol; 179 m_pTargetProtocol = pTargetProtocol;
122 bool isBlocked = false; 180 return BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTargetProtocol);
123 m_shouldBlock = false; 181 }
124 m_lastDataReported = false; 182
125 CString src; 183 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead)
126 src.Append(szUrl); 184 {
127 DEBUG_GENERAL(src); 185 if (!pv || !pcbRead)
128 CPluginClient::UnescapeUrl(src); 186 {
129 187 return E_POINTER;
130 CString boundDomain; 188 }
131 CString mimeType; 189 *pcbRead = 0;
132 LPOLESTR mime[10]; 190
133 if (pOIBindInfo) 191 if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent)
134 { 192 {
135 ULONG resLen = 0; 193 ULONG blockedByABPPageSize = static_cast<ULONG>(g_blockedByABPPage.size());
136 194 auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(blockedByABPPageS ize - m_currentPositionOfSentPage));
137 // Apparently IE will report random mime type if there's more then 1 in the list. 195 if (positionGrow == 0) {
138 // So we get the whole list and just use the first one (top priority one) 196 return S_FALSE;
139 pOIBindInfo->GetBindString(BINDSTRING_ACCEPT_MIMES, mime, 10, &resLen); 197 }
140 if (mime && resLen > 0) 198 std::copy(g_blockedByABPPage.begin(), g_blockedByABPPage.begin() + positionG row,
141 { 199 stdext::make_checked_array_iterator(static_cast<char*>(pv), cb));
142 mimeType.SetString(mime[0]); 200 *pcbRead = positionGrow;
143 } 201 m_currentPositionOfSentPage += positionGrow;
144 LPOLESTR bindToObject = 0; 202
145 pOIBindInfo->GetBindString(BINDSTRING_FLAG_BIND_TO_OBJECT, &bindToObject, 1, &resLen); 203 if (m_spInternetProtocolSink)
146 LPOLESTR domainRetrieved = 0; 204 {
147 if (resLen == 0 || wcscmp(bindToObject, L"FALSE") == 0) 205 m_spInternetProtocolSink->ReportData(BSCF_INTERMEDIATEDATANOTIFICATION,
148 { 206 static_cast<ULONG>(m_currentPositionOfSentPage), blockedByABPPageSize);
149 HRESULT hr = pOIBindInfo->GetBindString(BINDSTRING_XDR_ORIGIN, &domainRetr ieved, 1, &resLen); 207 }
150 208 if (blockedByABPPageSize == m_currentPositionOfSentPage && m_spInternetProto colSink)
151 if ((hr == S_OK) && domainRetrieved && (resLen > 0)) 209 {
152 { 210 m_spInternetProtocolSink->ReportData(BSCF_DATAFULLYAVAILABLE, blockedByABP PageSize, blockedByABPPageSize);
153 boundDomain.SetString(domainRetrieved); 211 m_spInternetProtocolSink->ReportResult(S_OK, 0, nullptr);
154 }
155 }
156 }
157
158 CString cookie;
159 ULONG len1 = 2048;
160 ULONG len2 = 2048;
161
162 #ifdef SUPPORT_FILTER
163 int contentType = CFilter::contentTypeAny;
164
165 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId());
166 CPluginClient* client = CPluginClient::GetInstance();
167
168
169 if (tab && client)
170 {
171 CString documentUrl = tab->GetDocumentUrl();
172 // Page is identical to document => don't block
173 if (documentUrl == src)
174 {
175 // fall through
176 }
177 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl)))
178 {
179 boundDomain = tab->GetDocumentUrl();
180
181 contentType = CFilter::contentTypeAny;
182
183 #ifdef SUPPORT_FRAME_CACHING
184 if ((tab != 0) && (tab->IsFrameCached(src)))
185 {
186 contentType = CFilter::contentTypeSubdocument;
187 }
188 else
189 #endif // SUPPORT_FRAME_CACHING
190 contentType = GetContentType(mimeType, boundDomain, src);
191 if (client->ShouldBlock(src, contentType, boundDomain, true))
192 {
193 isBlocked = true;
194
195 DEBUG_BLOCKER("Blocker::Blocking Http-request:" + src);
196 }
197 }
198 if (!isBlocked)
199 {
200 DEBUG_BLOCKER("Blocker::Ignoring Http-request:" + src)
201 }
202 }
203
204
205 if (tab == NULL)
206 {
207 contentType = GetContentType(mimeType, boundDomain, src);
208 if (client->ShouldBlock(src, contentType, boundDomain, true))
209 {
210 isBlocked = true;
211 }
212 }
213
214 #ifdef _DEBUG
215 CString type;
216
217 if (contentType == CFilter::contentTypeDocument) type = "DOCUMENT";
218 else if (contentType == CFilter::contentTypeObject) type = "OBJECT";
219 else if (contentType == CFilter::contentTypeImage) type = "IMAGE";
220 else if (contentType == CFilter::contentTypeScript) type = "SCRIPT";
221 else if (contentType == CFilter::contentTypeOther) type = "OTHER";
222 else if (contentType == CFilter::contentTypeUnknown) type = "OTHER";
223 else if (contentType == CFilter::contentTypeSubdocument) type = "SUBDOCUMENT";
224 else if (contentType == CFilter::contentTypeStyleSheet) type = "STYLESHEET";
225 else type = "OTHER";
226
227 if (isBlocked)
228 {
229 CPluginDebug::DebugResultBlocking(type, src, boundDomain);
230 }
231 else
232 {
233 CPluginDebug::DebugResultIgnoring(type, src, boundDomain);
234 }
235 #endif
236
237 //Fixes the iframe back button issue
238 if (AdblockPlus::IE::InstalledMajorVersion() > 6)
239 {
240 if ((contentType == CFilter::contentTypeImage) && (isBlocked))
241 {
242 m_shouldBlock = true;
243 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
244
245 return INET_E_REDIRECT_FAILED;
246
247 }
248 if (((contentType == CFilter::contentTypeSubdocument))&& (isBlocked))
249 {
250 m_shouldBlock = true;
251 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
252
253 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/html");
254
255 //Here we check if we are running on Windows 8 Consumer Preview.
256 //For some reason on that environment the next line causes IE to crash
257 if (CPluginSettings::GetInstance()->GetWindowsBuildNumber() != 8250)
258 {
259 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"res:// mshtml.dll/blank.htm");
260 }
261
262 return INET_E_REDIRECT_FAILED;
263 }
264 if (((contentType == CFilter::contentTypeScript)) && (isBlocked))
265 {
266 m_shouldBlock = true;
267 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
268 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/javascript");
269 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
270 return INET_E_REDIRECT_FAILED;
271 }
272 if ((contentType == CFilter::contentTypeXmlHttpRequest) && (isBlocked))
273 {
274 m_shouldBlock = true;
275 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
276 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
277 return INET_E_REDIRECT_FAILED;
278 }
279 if ((isBlocked))
280 {
281 m_shouldBlock = true;
282 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
283 m_spInternetProtocolSink->ReportResult(S_FALSE, 0, L"");
284
285 return INET_E_REDIRECT_FAILED;
286 }
287 }
288 #endif // SUPPORT_FILTER
289
290 return isBlocked ? S_FALSE : BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInf o, grfPI, dwReserved, pTargetProtocol);
291 }
292
293
294 HRESULT WBPassthruSink::Read(void *pv, ULONG cb, ULONG* pcbRead)
295 {
296 if (m_shouldBlock)
297 {
298 *pcbRead = 0;
299 if (!m_lastDataReported)
300 {
301 if (cb <= 1)
302 {
303 //IE must've gone nuts if this happened, but let's be cool about it and report we have no more data
304 m_spInternetProtocolSink->ReportResult(S_FALSE, 0, NULL);
305 return S_FALSE;
306 }
307 *pcbRead = 1;
308 memcpy(pv, " ", 1);
309
310 if (m_spInternetProtocolSink != NULL)
311 {
312 m_spInternetProtocolSink->ReportResult(S_OK, 0, NULL);
313 }
314 m_lastDataReported = true;
315 m_shouldBlock = false;
316 return S_OK;
317 } 212 }
318 return S_OK; 213 return S_OK;
319 } 214 }
320 else 215 return m_pTargetProtocol->Read(pv, cb, pcbRead);
321 {
322
323 return m_pTargetProtocol->Read(pv, cb, pcbRead);
324 }
325 return S_OK;
326 } 216 }
327 STDMETHODIMP WBPassthruSink::Switch( 217 STDMETHODIMP WBPassthruSink::Switch(
328 /* [in] */ PROTOCOLDATA *pProtocolData) 218 /* [in] */ PROTOCOLDATA *pProtocolData)
329 { 219 {
330 ATLASSERT(m_spInternetProtocolSink != 0); 220 ATLASSERT(m_spInternetProtocolSink != 0);
331 221
332 /* 222 /*
333 From Igor Tandetnik "itandetnik@mvps.org" 223 From Igor Tandetnik "itandetnik@mvps.org"
334 " 224 "
335 Beware multithreading. URLMon has this nasty habit of spinning worker 225 Beware multithreading. URLMon has this nasty habit of spinning worker
336 threads, not even bothering to initialize COM on them, and calling APP 226 threads, not even bothering to initialize COM on them, and calling APP
337 methods on those threads. If you try to raise COM events directly from 227 methods on those threads. If you try to raise COM events directly from
338 such a thread, bad things happen (random crashes, events being lost). 228 such a thread, bad things happen (random crashes, events being lost).
339 You are only guaranteed to be on the main STA thread in two cases. 229 You are only guaranteed to be on the main STA thread in two cases.
340 First, in methods of interfaces that were obtained with 230 First, in methods of interfaces that were obtained with
341 IServiceProvider, such as IHttpNegotiage::BeginningTransaction or 231 IServiceProvider, such as IHttpNegotiage::BeginningTransaction or
342 IAuthenticate::Authenticate. Second, you can call 232 IAuthenticate::Authenticate. Second, you can call
343 IInternetProtocolSink::Switch with PD_FORCE_SWITCH flag in 233 IInternetProtocolSink::Switch with PD_FORCE_SWITCH flag in
344 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call 234 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call
345 IInternetProtocol::Continue on the main thread. 235 IInternetProtocol::Continue on the main thread.
346 236
347 Or, if you happen to have a window handy that was created on the main 237 Or, if you happen to have a window handy that was created on the main
348 thread, you can post yourself a message. 238 thread, you can post yourself a message.
349 " 239 "
350 */ 240 */
351 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED; 241 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED;
352 } 242 }
353 243
354 244 // This is the heuristic which detects the requests issued by Flash.ocx.
355 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade rs, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) 245 // It turned out that the implementation from ''Flash.ocx'' (tested version is 1 5.0.0.152)
356 { 246 // returns quite minimal configuration in comparison with the implementation fro m Microsofts'
247 // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often inclu des something
248 // else.
249 bool WBPassthruSink::IsFlashRequest(const wchar_t* const* additionalHeaders)
250 {
251 if (additionalHeaders && *additionalHeaders)
252 {
253 auto flashVersionHeader = ExtractHttpHeader<std::wstring>(*additionalHeaders , L"x-flash-version:", L"\n");
254 if (!TrimString(flashVersionHeader).empty())
255 {
256 return true;
257 }
258 }
259 ATL::CComPtr<IBindStatusCallback> bscb;
260 if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb)
261 {
262 DWORD grfBINDF = 0;
263 BINDINFO bindInfo = {};
264 bindInfo.cbSize = sizeof(bindInfo);
265 if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo)) &&
266 (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF &&
267 (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindI nfo.dwOptions
268 )
269 {
270 return true;
271 }
272 }
273 return false;
274 }
275
276 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade rs, DWORD dwReserved, LPWSTR* pszAdditionalHeaders)
277 {
278 if (!szURL)
279 {
280 return E_POINTER;
281 }
282 std::wstring src = szURL;
283 DEBUG_GENERAL(ToCString(src));
284
285 std::string acceptHeader = ExtractHttpAcceptHeader(m_spTargetProtocol);
286 m_contentType = GetContentTypeFromMimeType(ATL::CString(acceptHeader.c_str())) ;
287
357 if (pszAdditionalHeaders) 288 if (pszAdditionalHeaders)
358 { 289 {
359 *pszAdditionalHeaders = 0; 290 *pszAdditionalHeaders = nullptr;
291 }
292
293 CComPtr<IHttpNegotiate> httpNegotiate;
294 QueryServiceFromClient(&httpNegotiate);
295 // This fills the pszAdditionalHeaders with more headers. One of which is the Referer header, which we need.
296 // There doesn't seem to be any other way to get this header before the reques t has been made.
297 HRESULT nativeHr = httpNegotiate ? httpNegotiate->BeginningTransaction(szURL, szHeaders, dwReserved, pszAdditionalHeaders) : S_OK;
298
299 if (pszAdditionalHeaders && *pszAdditionalHeaders)
300 {
301 m_boundDomain = ExtractHttpHeader<std::wstring>(*pszAdditionalHeaders, L"Ref erer:", L"\n");
302 }
303 m_boundDomain = TrimString(m_boundDomain);
304 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId());
305 CPluginClient* client = CPluginClient::GetInstance();
306
307 if (tab && client)
308 {
309 CString documentUrl = tab->GetDocumentUrl();
310 // Page is identical to document => don't block
311 if (documentUrl == ToCString(src))
312 {
313 return nativeHr;
314 }
315 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl)))
316 {
317 if (tab->IsFrameCached(ToCString(src)))
318 {
319 m_contentType = CFilter::contentTypeSubdocument;
320 }
321 }
322 }
323
324 if (IsFlashRequest(pszAdditionalHeaders))
325 {
326 m_contentType = CFilter::EContentType::contentTypeObjectSubrequest;
327 }
328
329 if (pszAdditionalHeaders && *pszAdditionalHeaders && IsXmlHttpRequest(*pszAddi tionalHeaders))
330 {
331 m_contentType = CFilter::EContentType::contentTypeXmlHttpRequest;
332 }
333
334 if (client->ShouldBlock(szURL, m_contentType, m_boundDomain, /*debug flag but must be set*/true))
335 {
336 // NOTE: Feeding custom HTML to Flash, instead of original object subrequest
337 // doesn't have much sense. It also can manifest in unwanted result»
338 // like video being blocked (See https://issues.adblockplus.org/ticket/1669) »
339 // So we report blocked object subrequests as failed, not just empty HTML.
340 m_isCustomResponse = m_contentType != CFilter::contentTypeObjectSubrequest;
341 return E_ABORT;
342 }
343 return nativeHr;
344 }
345
346 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
347 {
348 if (pszAdditionalRequestHeaders)
349 {
350 *pszAdditionalRequestHeaders = 0;
360 } 351 }
361 352
362 CComPtr<IHttpNegotiate> spHttpNegotiate; 353 CComPtr<IHttpNegotiate> spHttpNegotiate;
363 QueryServiceFromClient(&spHttpNegotiate); 354 QueryServiceFromClient(&spHttpNegotiate);
364 return spHttpNegotiate ? spHttpNegotiate->BeginningTransaction(szURL, szHeader s,dwReserved, pszAdditionalHeaders) : S_OK;
365 }
366
367 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
368 {
369 if (pszAdditionalRequestHeaders)
370 {
371 *pszAdditionalRequestHeaders = 0;
372 }
373
374 CComPtr<IHttpNegotiate> spHttpNegotiate;
375 QueryServiceFromClient(&spHttpNegotiate);
376 355
377 return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK; 356 return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK;
378 } 357 }
379 358
380 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus Text) 359 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus Text)
381 { 360 {
382 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK; 361 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK;
383 } 362 }
384 363
364 STDMETHODIMP WBPassthruSink::ReportResult(/* [in] */ HRESULT hrResult, /* [in] * / DWORD dwError, /* [in] */ LPCWSTR szResult)
365 {
366 if (m_isCustomResponse)
367 {
368 // Don't notify the client about aborting of the operation, thus don't call BaseClass::ReportResult.
369 // Current method is called by the original protocol implementation and we a re intercepting the
370 // call here and eating it, we will call the proper ReportResult later by ou rself.
371 return S_OK;
372 }
373 return BaseClass::ReportResult(hrResult, dwError, szResult);
374 }
375
376
377 WBPassthru::WBPassthru()
378 : m_shouldSupplyCustomContent(false)
379 {
380 }
385 381
386 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink , 382 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink ,
387 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) 383 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved)
388 { 384 {
389 ATLASSERT(m_spInternetProtocol != 0); 385 ATLASSERT(m_spInternetProtocol != 0);
390 if (!m_spInternetProtocol) 386 if (!m_spInternetProtocol)
391 { 387 {
392 return E_UNEXPECTED; 388 return E_UNEXPECTED;
393 } 389 }
394 390
395 return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, 391 return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, m_spInterne tProtocol);
396 dwReserved, m_spInternetProtocol); 392 }
397 } 393
398 394 STDMETHODIMP WBPassthru::Read(/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [o ut] */ ULONG *pcbRead)
399 STDMETHODIMP WBPassthru::Read(»/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [out] */ ULONG *pcbRead) 395 {
400 { 396 WBPassthruSink* pSink = GetSink();
401 397 return pSink->OnRead(pv, cb, pcbRead);
402 WBPassthruSink* pSink = GetSink(); 398 }
403 return pSink->Read(pv, cb, pcbRead);
404 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld