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

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

Issue 4974480757620736: Issue #1356 - Improve detection of the issuer of the request (Closed)
Left Patch Set: Update to the repositorory tip Created Oct. 24, 2014, 9:38 a.m.
Right Patch Set: Rename the parameter Created Nov. 5, 2014, 4:51 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
« no previous file with change/comment | « src/plugin/PluginWbPassThrough.h ('k') | src/plugin/SinkPolicy.inl » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include "PluginFilter.h" 6 #include "PluginFilter.h"
7 #include "PluginSettings.h" 7 #include "PluginSettings.h"
8 #include "PluginClass.h" 8 #include "PluginClass.h"
9 #include "PluginSystem.h" 9 #include "PluginSystem.h"
10 #include <WinInet.h> 10 #include <WinInet.h>
11 #include "wtypes.h" 11 #include "wtypes.h"
12 #include "../shared/Utils.h" 12 #include "../shared/Utils.h"
13 13
14 namespace 14 namespace
15 { 15 {
16 std::string g_blockedByABPPage = "<!DOCTYPE html>" 16 std::string g_blockedByABPPage = "<!DOCTYPE html>"
17 "<html>" 17 "<html>"
18 "<body>" 18 "<body>"
19 "<!-- blocked by AdblockPlus -->" 19 "<!-- blocked by AdblockPlus -->"
20 "</body>" 20 "</body>"
21 "</html>"; 21 "</html>";
22
23 template <class T>
24 T ExtractHttpHeader(const T& allHeaders, const T& targetHeaderNameWithColon, c onst T& delimiter)
25 {
26 auto targetHeaderBeginsAt = allHeaders.find(targetHeaderNameWithColon);
27 if (targetHeaderBeginsAt == T::npos)
28 {
29 return T();
30 }
31 targetHeaderBeginsAt += targetHeaderNameWithColon.length();
32 auto targetHeaderEndsAt = allHeaders.find(delimiter, targetHeaderBeginsAt);
33 if (targetHeaderEndsAt == T::npos)
34 {
35 return T();
36 }
37 return allHeaders.substr(targetHeaderBeginsAt, targetHeaderEndsAt - targetHe aderBeginsAt);
38 }
39
40 std::string ExtractHttpAcceptHeader(IInternetProtocol* internetProtocol)
41 {
42 // Despite there being HTTP_QUERY_ACCEPT and other query info flags, they do n't work here,
43 // only HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS does w ork.
44 ATL::CComPtr<IWinInetHttpInfo> winInetHttpInfo;
45 HRESULT hr = internetProtocol->QueryInterface(&winInetHttpInfo);
46 if (FAILED(hr))
47 {
48 return "";
49 }
50 DWORD size = 0;
51 DWORD flags = 0;
52 DWORD queryOption = HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HE ADERS;
53 hr = winInetHttpInfo->QueryInfo(queryOption, /*buffer*/ nullptr, /*get size* / &size, &flags, /*reserved*/ 0);
54 if (FAILED(hr))
55 {
56 return "";
57 }
58 std::string buf(size, '\0');
59 hr = winInetHttpInfo->QueryInfo(queryOption, &buf[0], &size, &flags, 0);
60 if (FAILED(hr))
61 {
62 return "";
63 }
64 return ExtractHttpHeader<std::string>(buf, "Accept:", "\r\n");
65 }
22 } 66 }
23 67
24 WBPassthruSink::WBPassthruSink() 68 WBPassthruSink::WBPassthruSink()
25 : m_currentPositionOfSentPage(0) 69 : m_currentPositionOfSentPage(0)
26 , m_contentType(CFilter::EContentType::contentTypeAny) 70 , m_contentType(CFilter::EContentType::contentTypeAny)
27 , m_blockedInTransaction(false) 71 , m_blockedInTransaction(false)
28 { 72 {
29 } 73 }
30 74
31 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType) 75 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType)
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call 231 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call
188 IInternetProtocol::Continue on the main thread. 232 IInternetProtocol::Continue on the main thread.
189 233
190 Or, if you happen to have a window handy that was created on the main 234 Or, if you happen to have a window handy that was created on the main
191 thread, you can post yourself a message. 235 thread, you can post yourself a message.
192 " 236 "
193 */ 237 */
194 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED; 238 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED;
195 } 239 }
196 240
241 // This is the heuristic which detects the requests issued by Flash.ocx.
242 // It turned out that the implementation from ''Flash.ocx'' (tested version is 1 5.0.0.152)
243 // returns quite minimal configuration in comparison with the implementation fro m Microsofts'
244 // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often inclu des something
245 // else.
246 bool WBPassthruSink::IsFlashRequest()
247 {
248 ATL::CComPtr<IBindStatusCallback> bscb;
249 if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb)
250 {
251 DWORD grfBINDF = 0;
252 BINDINFO bindInfo = {};
253 bindInfo.cbSize = sizeof(bindInfo);
254 if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo)) &&
255 (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF &&
256 (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindI nfo.dwOptions
257 )
258 {
259 return true;
260 }
261 }
262 return false;
263 }
264
197 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade rs, DWORD dwReserved, LPWSTR* pszAdditionalHeaders) 265 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade rs, DWORD dwReserved, LPWSTR* pszAdditionalHeaders)
198 { 266 {
267 std::wstring src = szURL;
268 DEBUG_GENERAL(ToCString(src));
269
270 std::string acceptHeader = ExtractHttpAcceptHeader(m_spTargetProtocol);
271 m_contentType = GetContentTypeFromMimeType(ATL::CString(acceptHeader.c_str())) ;
272
199 if (pszAdditionalHeaders) 273 if (pszAdditionalHeaders)
200 { 274 {
201 *pszAdditionalHeaders = nullptr; 275 *pszAdditionalHeaders = nullptr;
202 } 276 }
203 std::wstring src = szURL; 277
204 DEBUG_GENERAL(src); 278 CComPtr<IHttpNegotiate> httpNegotiate;
sergei 2014/10/28 14:08:46 DEBUG_GENERAL expects ATL::CString, it's not compi
205 279 QueryServiceFromClient(&httpNegotiate);
206 CComPtr<IHttpNegotiate> spHttpNegotiate;
207 QueryServiceFromClient(&spHttpNegotiate);
208 // This fills the pszAdditionalHeaders with more headers. One of which is the Referer header, which we need. 280 // This fills the pszAdditionalHeaders with more headers. One of which is the Referer header, which we need.
209 // There doesn't seem to be any other way to get this header before the reques t has been made. 281 // There doesn't seem to be any other way to get this header before the reques t has been made.
210 HRESULT nativeHr = spHttpNegotiate ? spHttpNegotiate->BeginningTransaction(szU RL, szHeaders,dwReserved, pszAdditionalHeaders) : S_OK; 282 HRESULT nativeHr = httpNegotiate ? httpNegotiate->BeginningTransaction(szURL, szHeaders, dwReserved, pszAdditionalHeaders) : S_OK;
211 283
212 auto acceptHeader = [&]() -> std::string
213 {
214 // Despite there is HTTP_QUERY_ACCEPT and other query info flags, they don't work here,
215 // only HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS does d ork.
216 ATL::CComPtr<IWinInetHttpInfo> winInetHttpInfo;
217 HRESULT hr = m_spTargetProtocol->QueryInterface(&winInetHttpInfo);
218 if(FAILED(hr))
219 {
220 return "";
221 }
222 DWORD size = 0;
223 DWORD flags = 0;
224 hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLA G_REQUEST_HEADERS,
225 /*buffer*/nullptr, /* get size */&size, &flags, /*reserved*/ 0);
226 if(FAILED(hr))
227 {
228 return "";
229 }
230 std::string buf(size, '\0');
231 hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLA G_REQUEST_HEADERS,
232 &buf[0], &size, &flags, 0);
233 if(FAILED(hr))
234 {
235 return "";
236 }
237 return ExtractHTTPHeader<std::string>(buf, "Accept:", "\r\n");
238 }();
239 m_contentType = GetContentTypeFromMimeType(ATL::CString(acceptHeader.c_str())) ;
240 if (*pszAdditionalHeaders != 0) 284 if (*pszAdditionalHeaders != 0)
241 { 285 {
242 m_boundDomain = ExtractHTTPHeader<std::wstring>(std::wstring(*pszAdditionalH eaders), L"Referer:", L"\n").c_str(); 286 m_boundDomain = ExtractHttpHeader<std::wstring>(*pszAdditionalHeaders, L"Ref erer:", L"\n").c_str();
243 } 287 }
244 m_boundDomain = TrimString(m_boundDomain); 288 m_boundDomain = TrimString(m_boundDomain);
245 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); 289 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId());
246 CPluginClient* client = CPluginClient::GetInstance(); 290 CPluginClient* client = CPluginClient::GetInstance();
247 291
248 if (tab && client) 292 if (tab && client)
249 { 293 {
250 CString documentUrl = tab->GetDocumentUrl(); 294 CString documentUrl = tab->GetDocumentUrl();
251 // Page is identical to document => don't block 295 // Page is identical to document => don't block
252 if (documentUrl == ToCString(src)) 296 if (documentUrl == ToCString(src))
253 { 297 {
254 return nativeHr; 298 return nativeHr;
255 } 299 }
256 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl))) 300 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl)))
257 { 301 {
258 if (tab->IsFrameCached(ToCString(src))) 302 if (tab->IsFrameCached(ToCString(src)))
259 { 303 {
260 m_contentType = CFilter::contentTypeSubdocument; 304 m_contentType = CFilter::contentTypeSubdocument;
261 } 305 }
262 } 306 }
263 } 307 }
264 308
265 { 309 if (IsFlashRequest())
266 // Here is the heuristic which detects the requests issued by Flash.ocx. 310 {
sergei 2014/10/28 14:08:46 I've also discovered that flash plugin on my compu
267 // It turned out that the implementation from ''Flash.ocx'' (tested version is 15.0.0.152) 311 m_contentType = CFilter::EContentType::contentTypeObjectSubrequest;
268 // returns quite minimal configuration in comparison with the implementation from Microsofts'
269 // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often i ncludes something
270 // else.
271 ATL::CComPtr<IBindStatusCallback> bscb;
272 if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb)
273 {
274 DWORD grfBINDF = 0;
275 BINDINFO bindInfo = {};
276 bindInfo.cbSize = sizeof(bindInfo);
277 if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo))
278 && (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF
279 && (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindInfo.dwOptions
280 )
281 {
282 m_contentType = CFilter::EContentType::contentTypeObjectSubrequest;
283 }
284 }
285 } 312 }
286 313
287 m_blockedInTransaction = client->ShouldBlock(szURL, m_contentType, m_boundDoma in, /*debug flag but must be set*/true); 314 m_blockedInTransaction = client->ShouldBlock(szURL, m_contentType, m_boundDoma in, /*debug flag but must be set*/true);
288 // For IE6 and earlier there is iframe back button issue, so avoid it.
sergei 2014/10/28 14:08:46 the comment is not relevant here
289 if (m_blockedInTransaction) 315 if (m_blockedInTransaction)
290 { 316 {
291 return E_ABORT; 317 return E_ABORT;
292 } 318 }
293 return nativeHr; 319 return nativeHr;
294 } 320 }
295 321
296 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) 322 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
297 { 323 {
298 if (pszAdditionalRequestHeaders) 324 if (pszAdditionalRequestHeaders)
(...skipping 11 matching lines...) Expand all
310 { 336 {
311 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK; 337 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK;
312 } 338 }
313 339
314 STDMETHODIMP WBPassthruSink::ReportResult(/* [in] */ HRESULT hrResult, /* [in] * / DWORD dwError, /* [in] */ LPCWSTR szResult) 340 STDMETHODIMP WBPassthruSink::ReportResult(/* [in] */ HRESULT hrResult, /* [in] * / DWORD dwError, /* [in] */ LPCWSTR szResult)
315 { 341 {
316 if (m_blockedInTransaction) 342 if (m_blockedInTransaction)
317 { 343 {
318 // Don't notify the client about aborting of the operation, thus don't call BaseClass::ReportResult. 344 // Don't notify the client about aborting of the operation, thus don't call BaseClass::ReportResult.
319 // Current method is called by the original protocol implementation and we a re intercepting the 345 // Current method is called by the original protocol implementation and we a re intercepting the
320 // call here and eating it, we will call the proper ReportResult later by ou rself. 346 // call here and eating it, we will call the proper ReportResult later by ou rself.
sergei 2014/10/28 14:08:46 The code is correct but I've recognized that the c
321 return S_OK; 347 return S_OK;
322 } 348 }
323 return BaseClass::ReportResult(hrResult, dwError, szResult); 349 return BaseClass::ReportResult(hrResult, dwError, szResult);
324 } 350 }
325 351
326 352
327 WBPassthru::WBPassthru() 353 WBPassthru::WBPassthru()
328 : m_shouldSupplyCustomContent(false) 354 : m_shouldSupplyCustomContent(false)
329 , m_hasOriginalStartCalled(false)
330 { 355 {
331 } 356 }
332 357
333 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink , 358 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink ,
334 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) 359 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved)
335 { 360 {
336 ATLASSERT(m_spInternetProtocol != 0); 361 ATLASSERT(m_spInternetProtocol != 0);
337 if (!m_spInternetProtocol) 362 if (!m_spInternetProtocol)
338 { 363 {
339 return E_UNEXPECTED; 364 return E_UNEXPECTED;
340 } 365 }
341 366
342 return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, m_spInterne tProtocol); 367 return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, m_spInterne tProtocol);
343 } 368 }
344 369
345 STDMETHODIMP WBPassthru::Read(/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [o ut] */ ULONG *pcbRead) 370 STDMETHODIMP WBPassthru::Read(/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [o ut] */ ULONG *pcbRead)
346 { 371 {
347 WBPassthruSink* pSink = GetSink(); 372 WBPassthruSink* pSink = GetSink();
348 return pSink->OnRead(pv, cb, pcbRead); 373 return pSink->OnRead(pv, cb, pcbRead);
349 } 374 }
350 375
351 STDMETHODIMP WBPassthru::LockRequest(/* [in] */ DWORD options) 376 STDMETHODIMP WBPassthru::LockRequest(/* [in] */ DWORD options)
352 { 377 {
353 if (!m_hasOriginalStartCalled)
354 {
355 return S_OK;
356 }
357 return BaseClass::LockRequest(options); 378 return BaseClass::LockRequest(options);
358 } 379 }
359 380
360 STDMETHODIMP WBPassthru::UnlockRequest() 381 STDMETHODIMP WBPassthru::UnlockRequest()
361 { 382 {
362 if (!m_hasOriginalStartCalled)
sergei 2014/10/28 14:08:46 Since we always call original Start let's delete m
363 {
364 return S_OK;
365 }
366 return BaseClass::UnlockRequest(); 383 return BaseClass::UnlockRequest();
367 } 384 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld