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

Side by Side Diff: src/plugin/PluginWbPassThrough.cpp

Issue 6299667012780032: Issues #696,1231,1264,1265 - Improve handling in PassthroughApp (Closed)
Patch Set: rebase Created Oct. 17, 2014, 12:51 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/plugin/PluginWbPassThrough.h ('k') | src/plugin/SinkPolicy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 10 #include <WinInet.h>
11 #include "wtypes.h" 11 #include "wtypes.h"
12 12
13 EXTERN_C IMAGE_DOS_HEADER __ImageBase; 13 namespace
14 {
15 std::string g_blockedByABPPage = "<!DOCTYPE html>"
16 "<html>"
17 "<body>"
18 "<!-- blocked by AdblockPlus -->"
19 "</body>"
20 "</html>";
21 }
14 22
23 WBPassthruSink::WBPassthruSink()
24 : m_currentPositionOfSentPage(0)
25 , m_contentType(CFilter::EContentType::contentTypeAny)
26 , m_blockedInTransaction(false)
27 {
28 }
15 29
16 30 int WBPassthruSink::GetContentTypeFromMimeType(const CString& mimeType)
17 int WBPassthruSink::GetContentTypeFromMimeType(CString mimeType)
18 { 31 {
19 if (mimeType.Find(L"image/") >= 0) 32 if (mimeType.Find(L"image/") >= 0)
20 { 33 {
21 return CFilter::contentTypeImage; 34 return CFilter::contentTypeImage;
22 } 35 }
23 if (mimeType.Find(L"text/css") >= 0) 36 if (mimeType.Find(L"text/css") >= 0)
24 { 37 {
25 return CFilter::contentTypeStyleSheet; 38 return CFilter::contentTypeStyleSheet;
26 } 39 }
27 if ((mimeType.Find(L"application/javascript") >= 0) || (mimeType.Find(L"applic ation/json") >= 0)) 40 if ((mimeType.Find(L"application/javascript") >= 0) || (mimeType.Find(L"applic ation/json") >= 0))
(...skipping 10 matching lines...) Expand all
38 } 51 }
39 // It is important to have this check last, since it is rather generic, and mi ght overlay text/html, for example 52 // It is important to have this check last, since it is rather generic, and mi ght overlay text/html, for example
40 if (mimeType.Find(L"xml") >= 0) 53 if (mimeType.Find(L"xml") >= 0)
41 { 54 {
42 return CFilter::contentTypeXmlHttpRequest; 55 return CFilter::contentTypeXmlHttpRequest;
43 } 56 }
44 57
45 return CFilter::contentTypeAny; 58 return CFilter::contentTypeAny;
46 } 59 }
47 60
48 int WBPassthruSink::GetContentTypeFromURL(CString src) 61 int WBPassthruSink::GetContentTypeFromURL(const CString& src)
49 { 62 {
50 CString srcExt = src; 63 CString srcExt = src;
51 64
52 int pos = 0; 65 int pos = 0;
53 if ((pos = src.Find('?')) > 0) 66 if ((pos = src.Find('?')) > 0)
54 { 67 {
55 srcExt = src.Left(pos); 68 srcExt = src.Left(pos);
56 } 69 }
57 70
58 int lastDotIndex = srcExt.ReverseFind('.'); 71 int lastDotIndex = srcExt.ReverseFind('.');
(...skipping 17 matching lines...) Expand all
76 return CFilter::contentTypeXmlHttpRequest; 89 return CFilter::contentTypeXmlHttpRequest;
77 } 90 }
78 else if (ext == L".swf") 91 else if (ext == L".swf")
79 { 92 {
80 return CFilter::contentTypeObject; 93 return CFilter::contentTypeObject;
81 } 94 }
82 else if (ext == L".jsp" || ext == L".php" || ext == L".html") 95 else if (ext == L".jsp" || ext == L".php" || ext == L".html")
83 { 96 {
84 return CFilter::contentTypeSubdocument; 97 return CFilter::contentTypeSubdocument;
85 } 98 }
86 else 99 return CFilter::contentTypeAny;
87 {
88 return CFilter::contentTypeAny & ~CFilter::contentTypeSubdocument;
89 }
90
91 } 100 }
92 101
93 int WBPassthruSink::GetContentType(CString mimeType, std::wstring domain, CStrin g src) 102 int WBPassthruSink::GetContentType(const CString& mimeType, const std::wstring& domain, const CString& src)
94 { 103 {
95 // No referer or mime type 104 // No referer or mime type
96 // BINDSTRING_XDR_ORIGIN works only for IE v8+ 105 // BINDSTRING_XDR_ORIGIN works only for IE v8+
97 if (mimeType.IsEmpty() && domain.empty() && CPluginClient::GetInstance()->GetI EVersion() >= 8) 106 if (mimeType.IsEmpty() && domain.empty() && CPluginClient::GetInstance()->GetI EVersion() >= 8)
98 { 107 {
99 return CFilter::contentTypeXmlHttpRequest; 108 return CFilter::contentTypeXmlHttpRequest;
100 } 109 }
101 int contentType = GetContentTypeFromMimeType(mimeType); 110 int contentType = GetContentTypeFromMimeType(mimeType);
102 if (contentType == CFilter::contentTypeAny) 111 if (contentType == CFilter::contentTypeAny)
103 { 112 {
104 contentType = GetContentTypeFromURL(src); 113 contentType = GetContentTypeFromURL(src);
105 } 114 }
106 return contentType; 115 return contentType;
107 } 116 }
108 117
109 //////////////////////////////////////////////////////////////////////////////// //////// 118 //////////////////////////////////////////////////////////////////////////////// ////////
110 //WBPassthruSink 119 //WBPassthruSink
111 //Monitor and/or cancel every request and responde 120 //Monitor and/or cancel every request and responde
112 //WB makes, including images, sounds, scripts, etc 121 //WB makes, including images, sounds, scripts, etc
113 //////////////////////////////////////////////////////////////////////////////// //////// 122 //////////////////////////////////////////////////////////////////////////////// ////////
114 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k, 123 HRESULT WBPassthruSink::OnStart(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSin k,
115 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN DLE_PTR dwReserved, 124 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HAN DLE_PTR dwReserved,
116 IInternetProtocol* pTargetProtocol) 125 IInternetProtocol* pTargetProtocol, bool& handle d)
117 { 126 {
118
119 m_pTargetProtocol = pTargetProtocol; 127 m_pTargetProtocol = pTargetProtocol;
120 bool isBlocked = false; 128 bool isBlocked = false;
121 m_shouldBlock = false; 129 CString src = szUrl;
122 m_lastDataReported = false;
123 CString src;
124 src.Append(szUrl);
125 DEBUG_GENERAL(src); 130 DEBUG_GENERAL(src);
126 CPluginClient::UnescapeUrl(src); 131 CPluginClient::UnescapeUrl(src);
127 132
128 std::wstring boundDomain; 133 // call the impl of the base class as soon as possible because it initializes the base class
134 // members, used by this method. It queries for the required interfaces.
135 HRESULT hr = BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwRese rved, pTargetProtocol);
136 if (FAILED(hr))
137 {
138 return hr;
139 }
140
129 CString mimeType; 141 CString mimeType;
130 LPOLESTR mime[10];
131 if (pOIBindInfo) 142 if (pOIBindInfo)
132 { 143 {
133 ULONG resLen = 0; 144 ULONG resLen = 0;
134 145
135 // Apparently IE will report random mime type if there's more then 1 in the list. 146 // Apparently IE will report random mime type if there's more then 1 in the list.
136 // So we get the whole list and just use the first one (top priority one) 147 // So we get the whole list and just use the first one (top priority one)
148 LPOLESTR mime[10];
137 pOIBindInfo->GetBindString(BINDSTRING_ACCEPT_MIMES, mime, 10, &resLen); 149 pOIBindInfo->GetBindString(BINDSTRING_ACCEPT_MIMES, mime, 10, &resLen);
138 if (mime && resLen > 0) 150 if (mime && resLen > 0)
139 { 151 {
140 mimeType.SetString(mime[0]); 152 mimeType.SetString(mime[0]);
141 } 153 }
142 LPOLESTR bindToObject = 0; 154 LPOLESTR bindString = nullptr;
143 pOIBindInfo->GetBindString(BINDSTRING_FLAG_BIND_TO_OBJECT, &bindToObject, 1, &resLen); 155 pOIBindInfo->GetBindString(BINDSTRING_FLAG_BIND_TO_OBJECT, &bindString, 1, & resLen);
144 wchar_t* domainRetrieved = 0; 156 LPOLESTR domainRetrieved = nullptr;
145 if (resLen == 0 || wcscmp(bindToObject, L"FALSE") == 0) 157 if (resLen == 0 || wcscmp(bindString, L"FALSE") == 0)
146 { 158 {
147 HRESULT hr = pOIBindInfo->GetBindString(BINDSTRING_XDR_ORIGIN, &domainRetr ieved, 1, &resLen); 159 HRESULT hr = pOIBindInfo->GetBindString(BINDSTRING_XDR_ORIGIN, &domainRetr ieved, 1, &resLen);
148
149 if ((hr == S_OK) && domainRetrieved && (resLen > 0)) 160 if ((hr == S_OK) && domainRetrieved && (resLen > 0))
150 { 161 {
151 boundDomain = std::wstring(domainRetrieved); 162 m_boundDomain = domainRetrieved;
152 } 163 }
153 } 164 }
165 // We can obtain IBindCtx* here, but IEnumString obtained via IBindCtx::Enum ObjectParam
166 // does not return any parameter, so it's useless.
154 } 167 }
155 168
156 CString cookie; 169 CString cookie;
157 ULONG len1 = 2048; 170 ULONG len1 = 2048;
158 ULONG len2 = 2048; 171 ULONG len2 = 2048;
159 172
160 int contentType = CFilter::contentTypeAny;
161
162 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId()); 173 CPluginTab* tab = CPluginClass::GetTab(::GetCurrentThreadId());
163 CPluginClient* client = CPluginClient::GetInstance(); 174 CPluginClient* client = CPluginClient::GetInstance();
164 175
165
166 if (tab && client) 176 if (tab && client)
167 { 177 {
168 CString documentUrl = tab->GetDocumentUrl(); 178 CString documentUrl = tab->GetDocumentUrl();
169 // Page is identical to document => don't block 179 // Page is identical to document => don't block
170 if (documentUrl == src) 180 if (documentUrl == src)
171 { 181 {
172 // fall through 182 // fall through
173 } 183 }
174 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(to_wstring(documentUrl))) 184 else if (CPluginSettings::GetInstance()->IsPluginEnabled() && !client->IsWhi telistedUrl(std::wstring(documentUrl)))
175 { 185 {
176 boundDomain = to_wstring(tab->GetDocumentUrl()); 186 m_boundDomain = tab->GetDocumentUrl();
177 contentType = CFilter::contentTypeAny; 187 m_contentType = CFilter::contentTypeAny;
178 if ((tab != 0) && (tab->IsFrameCached(src))) 188 if (tab != nullptr && tab->IsFrameCached(src))
179 { 189 {
180 contentType = CFilter::contentTypeSubdocument; 190 m_contentType = CFilter::contentTypeSubdocument;
181 } 191 }
182 else 192 else
183 { 193 {
184 contentType = GetContentType(mimeType, boundDomain, src); 194 m_contentType = GetContentType(mimeType, m_boundDomain, src);
185 } 195 }
186 if (client->ShouldBlock(to_wstring(src), contentType, boundDomain, true))
187 {
188 isBlocked = true;
189 DEBUG_BLOCKER("Blocker::Blocking Http-request:" + src);
190 }
191 }
192 if (!isBlocked)
193 {
194 DEBUG_BLOCKER("Blocker::Ignoring Http-request:" + src)
195 } 196 }
196 } 197 }
197 198
199 if (tab == nullptr)
200 {
201 m_contentType = GetContentType(mimeType, m_boundDomain, src);
202 }
198 203
199 if (tab == NULL)
200 { 204 {
201 contentType = GetContentType(mimeType, boundDomain, src); 205 // Here is the heuristic which detects the requests issued by Flash.ocx.
202 if (client->ShouldBlock(to_wstring(src), contentType, boundDomain, true)) 206 // It turned out that the implementation from ''Flash.ocx'' (tested version is 15.0.0.152)
207 // returns quite minimal configuration in comparison with the implementation from Microsofts'
208 // libraries (see grfBINDF and bindInfo.dwOptions). The impl from MS often i ncludes something
209 // else.
210 ATL::CComPtr<IBindStatusCallback> bscb;
211 if (SUCCEEDED(QueryServiceFromClient(&bscb)) && !!bscb)
203 { 212 {
204 isBlocked = true; 213 DWORD grfBINDF = 0;
214 BINDINFO bindInfo = {};
215 bindInfo.cbSize = sizeof(bindInfo);
216 if (SUCCEEDED(bscb->GetBindInfo(&grfBINDF, &bindInfo))
217 && (BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE| BINDF_PULLDATA) == grfBINDF
218 && (BINDINFO_OPTIONS_ENABLE_UTF8 | BINDINFO_OPTIONS_USE_IE_ENCODING) == bindInfo.dwOptions
219 )
220 {
221 m_contentType = CFilter::EContentType::contentTypeObjectSubrequest;
222 }
205 } 223 }
206 } 224 }
207 225
208 #ifdef _DEBUG 226 // The descision about EContentType::contentTypeAny is made later in
209 CString type; 227 // WBPassthruSink::BeginningTransaction. Sometimes here we cannot detect the r equest type, but
228 // in WBPassthruSink::BeginningTransaction the header Accept is available whic h allows to
229 // obtain the "request type" in our terminology.
230 if (nullptr != client
231 && CFilter::EContentType::contentTypeAny != m_contentType
232 && client->ShouldBlock(static_cast<const wchar_t*>(src), m_contentType, m_bo undDomain, true))
233 {
234 isBlocked = true;
235 }
210 236
211 if (contentType == CFilter::contentTypeDocument) type = "DOCUMENT"; 237 // For IE6 and earlier there is iframe back button issue, so avoid it.
212 else if (contentType == CFilter::contentTypeObject) type = "OBJECT"; 238 if (isBlocked && client->GetIEVersion() > 6)
213 else if (contentType == CFilter::contentTypeImage) type = "IMAGE";
214 else if (contentType == CFilter::contentTypeScript) type = "SCRIPT";
215 else if (contentType == CFilter::contentTypeOther) type = "OTHER";
216 else if (contentType == CFilter::contentTypeUnknown) type = "OTHER";
217 else if (contentType == CFilter::contentTypeSubdocument) type = "SUBDOCUMENT";
218 else if (contentType == CFilter::contentTypeStyleSheet) type = "STYLESHEET";
219 else type = "OTHER";
220
221 if (isBlocked)
222 { 239 {
223 CPluginDebug::DebugResultBlocking(type, src, boundDomain); 240 handled = true;
224 } 241 if (CFilter::EContentType::contentTypeImage == m_contentType)
225 else
226 {
227 CPluginDebug::DebugResultIgnoring(type, src, boundDomain);
228 }
229 #endif
230
231 //Fixes the iframe back button issue
232 if (client->GetIEVersion() > 6)
233 {
234 if ((contentType == CFilter::contentTypeImage) && (isBlocked))
235 { 242 {
236 m_shouldBlock = true; 243 // IE shows a cross that img is not loaded
237 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
238
239 return INET_E_REDIRECT_FAILED; 244 return INET_E_REDIRECT_FAILED;
240
241 } 245 }
242 if (((contentType == CFilter::contentTypeSubdocument))&& (isBlocked)) 246 if (CFilter::EContentType::contentTypeSubdocument == m_contentType)
243 { 247 {
244 m_shouldBlock = true; 248 PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent = true;
245 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
246
247 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/html"); 249 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/html");
248 250 m_spInternetProtocolSink->ReportData(BSCF_FIRSTDATANOTIFICATION, 0, static _cast<ULONG>(g_blockedByABPPage.size()));
249 //Here we check if we are running on Windows 8 Consumer Preview. 251 return S_OK;
250 //For some reason on that environment the next line causes IE to crash
251 if (CPluginSettings::GetInstance()->GetWindowsBuildNumber() != 8250)
252 {
253 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECT_FAILED, 0, szUrl) ;
254 }
255
256 return INET_E_REDIRECT_FAILED;
257 } 252 }
258 if (((contentType == CFilter::contentTypeScript)) && (isBlocked)) 253 if (CFilter::EContentType::contentTypeScript == m_contentType)
259 { 254 {
260 m_shouldBlock = true;
261 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
262 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/javascript"); 255 m_spInternetProtocolSink->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, L"t ext/javascript");
263 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); 256 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
264 return INET_E_REDIRECT_FAILED; 257 return INET_E_REDIRECT_FAILED;
265 } 258 }
266 if ((contentType == CFilter::contentTypeXmlHttpRequest) && (isBlocked)) 259 if (CFilter::EContentType::contentTypeXmlHttpRequest == m_contentType)
267 { 260 {
268 m_shouldBlock = true;
269 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
270 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:"); 261 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
271 return INET_E_REDIRECT_FAILED; 262 return INET_E_REDIRECT_FAILED;
272 } 263 }
273 if ((isBlocked)) 264 if (CFilter::EContentType::contentTypeAny != m_contentType)
274 { 265 {
275 m_shouldBlock = true; 266 m_spInternetProtocolSink->ReportResult(INET_E_REDIRECTING, 301, L"data:");
276 BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, pTa rgetProtocol);
277 m_spInternetProtocolSink->ReportResult(S_FALSE, 0, L"");
278
279 return INET_E_REDIRECT_FAILED; 267 return INET_E_REDIRECT_FAILED;
280 } 268 }
281 } 269 }
282 return isBlocked ? S_FALSE : BaseClass::OnStart(szUrl, pOIProtSink, pOIBindInf o, grfPI, dwReserved, pTargetProtocol); 270
271 return isBlocked ? S_FALSE : hr;
283 } 272 }
284 273
274 HRESULT WBPassthruSink::OnRead(void* pv, ULONG cb, ULONG* pcbRead)
275 {
276 if (pv == nullptr)
277 {
278 return E_POINTER;
279 }
280 if (pcbRead == nullptr)
281 {
282 return E_POINTER;
283 }
284 *pcbRead = 0;
285 285
286 HRESULT WBPassthruSink::Read(void *pv, ULONG cb, ULONG* pcbRead) 286 if (PassthroughAPP::CustomSinkStartPolicy<WBPassthru, WBPassthruSink>::GetProt ocol(this)->m_shouldSupplyCustomContent)
287 {
288 if (m_shouldBlock)
289 { 287 {
290 *pcbRead = 0; 288 ULONG blockedByABPPageSize = static_cast<ULONG>(g_blockedByABPPage.size());
291 if (!m_lastDataReported) 289 auto positionGrow = std::min<ULONG>(cb, static_cast<ULONG>(blockedByABPPageS ize - m_currentPositionOfSentPage));
290 if (positionGrow == 0) {
291 return S_FALSE;
292 }
293 std::copy(g_blockedByABPPage.begin(), g_blockedByABPPage.begin() + positionG row,
294 stdext::make_checked_array_iterator(static_cast<char*>(pv), cb));
295 *pcbRead = positionGrow;
296 m_currentPositionOfSentPage += positionGrow;
297
298 if (m_spInternetProtocolSink)
292 { 299 {
293 if (cb <= 1) 300 m_spInternetProtocolSink->ReportData(BSCF_INTERMEDIATEDATANOTIFICATION,
294 { 301 static_cast<ULONG>(m_currentPositionOfSentPage), blockedByABPPageSize);
295 //IE must've gone nuts if this happened, but let's be cool about it and report we have no more data 302 }
296 m_spInternetProtocolSink->ReportResult(S_FALSE, 0, NULL); 303 if (blockedByABPPageSize == m_currentPositionOfSentPage && m_spInternetProto colSink)
297 return S_FALSE; 304 {
298 } 305 m_spInternetProtocolSink->ReportData(BSCF_DATAFULLYAVAILABLE, blockedByABP PageSize, blockedByABPPageSize);
299 *pcbRead = 1; 306 m_spInternetProtocolSink->ReportResult(S_OK, 0, nullptr);
300 memcpy(pv, " ", 1);
301
302 if (m_spInternetProtocolSink != NULL)
303 {
304 m_spInternetProtocolSink->ReportResult(S_OK, 0, NULL);
305 }
306 m_lastDataReported = true;
307 m_shouldBlock = false;
308 return S_OK;
309 } 307 }
310 return S_OK; 308 return S_OK;
311 } 309 }
312 else 310 return m_pTargetProtocol->Read(pv, cb, pcbRead);
313 {
314
315 return m_pTargetProtocol->Read(pv, cb, pcbRead);
316 }
317 return S_OK;
318 } 311 }
319 STDMETHODIMP WBPassthruSink::Switch( 312 STDMETHODIMP WBPassthruSink::Switch(
320 /* [in] */ PROTOCOLDATA *pProtocolData) 313 /* [in] */ PROTOCOLDATA *pProtocolData)
321 { 314 {
322 ATLASSERT(m_spInternetProtocolSink != 0); 315 ATLASSERT(m_spInternetProtocolSink != 0);
323 316
324 /* 317 /*
325 From Igor Tandetnik "itandetnik@mvps.org" 318 From Igor Tandetnik "itandetnik@mvps.org"
326 " 319 "
327 Beware multithreading. URLMon has this nasty habit of spinning worker 320 Beware multithreading. URLMon has this nasty habit of spinning worker
328 threads, not even bothering to initialize COM on them, and calling APP 321 threads, not even bothering to initialize COM on them, and calling APP
329 methods on those threads. If you try to raise COM events directly from 322 methods on those threads. If you try to raise COM events directly from
330 such a thread, bad things happen (random crashes, events being lost). 323 such a thread, bad things happen (random crashes, events being lost).
331 You are only guaranteed to be on the main STA thread in two cases. 324 You are only guaranteed to be on the main STA thread in two cases.
332 First, in methods of interfaces that were obtained with 325 First, in methods of interfaces that were obtained with
333 IServiceProvider, such as IHttpNegotiage::BeginningTransaction or 326 IServiceProvider, such as IHttpNegotiage::BeginningTransaction or
334 IAuthenticate::Authenticate. Second, you can call 327 IAuthenticate::Authenticate. Second, you can call
335 IInternetProtocolSink::Switch with PD_FORCE_SWITCH flag in 328 IInternetProtocolSink::Switch with PD_FORCE_SWITCH flag in
336 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call 329 PROTOCOLDATA::grfFlags, eventually URLMon will turn around and call
337 IInternetProtocol::Continue on the main thread. 330 IInternetProtocol::Continue on the main thread.
338 331
339 Or, if you happen to have a window handy that was created on the main 332 Or, if you happen to have a window handy that was created on the main
340 thread, you can post yourself a message. 333 thread, you can post yourself a message.
341 " 334 "
342 */ 335 */
343 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED; 336 return m_spInternetProtocolSink ? m_spInternetProtocolSink->Switch(pProtocolDa ta) : E_UNEXPECTED;
344 } 337 }
345 338
346 339 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade rs, DWORD dwReserved, LPWSTR* pszAdditionalHeaders)
347 STDMETHODIMP WBPassthruSink::BeginningTransaction(LPCWSTR szURL, LPCWSTR szHeade rs, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
348 { 340 {
349 if (pszAdditionalHeaders) 341 if (pszAdditionalHeaders)
350 { 342 {
351 *pszAdditionalHeaders = 0; 343 *pszAdditionalHeaders = nullptr;
352 } 344 }
353 345
346 CPluginClient* client = nullptr;
347 if (CFilter::EContentType::contentTypeAny == m_contentType && (client = CPlugi nClient::GetInstance()))
348 {
349 auto acceptHeader = [&]() -> std::string
350 {
351 // Despite there is HTTP_QUERY_ACCEPT and other query info flags, they don 't work here,
352 // only HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_FLAG_REQUEST_HEADERS does dork.
353 ATL::CComPtr<IWinInetHttpInfo> winInetHttpInfo;
354 HRESULT hr = m_spTargetProtocol->QueryInterface(&winInetHttpInfo);
355 if(FAILED(hr))
356 {
357 return "";
358 }
359 DWORD size = 0;
360 DWORD flags = 0;
361 hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_F LAG_REQUEST_HEADERS,
362 /*buffer*/nullptr, /* get size */&size, &flags, /*reserved*/ 0);
363 if(FAILED(hr))
364 {
365 return "";
366 }
367 std::string buf(size, '\0');
368 hr = winInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS_CRLF | HTTP_QUERY_F LAG_REQUEST_HEADERS,
369 &buf[0], &size, &flags, 0);
370 if(FAILED(hr))
371 {
372 return "";
373 }
374 char acceptHeader[] = "Accept:";
375 auto acceptHeaderBeginsAt = buf.find(acceptHeader);
376 if (std::string::npos == acceptHeaderBeginsAt)
377 {
378 return "";
379 }
380 acceptHeaderBeginsAt += sizeof(acceptHeader);
381 auto acceptHeaderEndsAt = buf.find("\n", acceptHeaderBeginsAt);
382 if (std::string::npos == acceptHeaderEndsAt)
383 {
384 return "";
385 }
386 return buf.substr(acceptHeaderBeginsAt, acceptHeaderEndsAt - acceptHeaderB eginsAt);
387 }();
388 m_contentType = GetContentTypeFromMimeType(ATL::CString(acceptHeader.c_str() ));
389 bool isBlocked = client->ShouldBlock(szURL, m_contentType, m_boundDomain, /* debug flag but must be set*/true);
390 if (isBlocked)
391 {
392 m_blockedInTransaction = true;
393 return E_ABORT;
394 }
395 }
354 CComPtr<IHttpNegotiate> spHttpNegotiate; 396 CComPtr<IHttpNegotiate> spHttpNegotiate;
355 QueryServiceFromClient(&spHttpNegotiate); 397 QueryServiceFromClient(&spHttpNegotiate);
356 return spHttpNegotiate ? spHttpNegotiate->BeginningTransaction(szURL, szHeader s,dwReserved, pszAdditionalHeaders) : S_OK; 398 return spHttpNegotiate ? spHttpNegotiate->BeginningTransaction(szURL, szHeader s,dwReserved, pszAdditionalHeaders) : S_OK;
357 } 399 }
358 400
359 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) 401 STDMETHODIMP WBPassthruSink::OnResponse(DWORD dwResponseCode, LPCWSTR szResponse Headers, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
360 { 402 {
361 if (pszAdditionalRequestHeaders) 403 if (pszAdditionalRequestHeaders)
362 { 404 {
363 *pszAdditionalRequestHeaders = 0; 405 *pszAdditionalRequestHeaders = 0;
364 } 406 }
365 407
366 CComPtr<IHttpNegotiate> spHttpNegotiate; 408 CComPtr<IHttpNegotiate> spHttpNegotiate;
367 QueryServiceFromClient(&spHttpNegotiate); 409 QueryServiceFromClient(&spHttpNegotiate);
368 410
369 return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK; 411 return spHttpNegotiate ? spHttpNegotiate->OnResponse(dwResponseCode, szRespons eHeaders, szRequestHeaders, pszAdditionalRequestHeaders) : S_OK;
370 } 412 }
371 413
372 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus Text) 414 STDMETHODIMP WBPassthruSink::ReportProgress(ULONG ulStatusCode, LPCWSTR szStatus Text)
373 { 415 {
374 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK; 416 return m_spInternetProtocolSink ? m_spInternetProtocolSink->ReportProgress(ulS tatusCode, szStatusText) : S_OK;
375 } 417 }
376 418
419 STDMETHODIMP WBPassthruSink::ReportResult(/* [in] */ HRESULT hrResult, /* [in] * / DWORD dwError, /* [in] */ LPCWSTR szResult)
420 {
421 if (m_blockedInTransaction)
422 {
423 // Don't notify the client about aborting of the operation, thus don't call BaseClass::ReportResult.
424 // Current method is called by the original protocol implementation and we a re intercepting the
425 // call here and eating it, we will call the proper ReportResult later by ou rself.
426 return S_OK;
427 }
428 return BaseClass::ReportResult(hrResult, dwError, szResult);
429 }
430
431
432 WBPassthru::WBPassthru()
433 : m_shouldSupplyCustomContent(false)
434 , m_hasOriginalStartCalled(false)
435 {
436 }
377 437
378 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink , 438 STDMETHODIMP WBPassthru::Start(LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink ,
379 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) 439 IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved)
380 { 440 {
381 ATLASSERT(m_spInternetProtocol != 0); 441 ATLASSERT(m_spInternetProtocol != 0);
382 if (!m_spInternetProtocol) 442 if (!m_spInternetProtocol)
383 { 443 {
384 return E_UNEXPECTED; 444 return E_UNEXPECTED;
385 } 445 }
386 446
387 return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, 447 return OnStart(szUrl, pOIProtSink, pOIBindInfo, grfPI, dwReserved, m_spInterne tProtocol);
388 dwReserved, m_spInternetProtocol);
389 } 448 }
390 449
391 STDMETHODIMP WBPassthru::Read(»/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [out] */ ULONG *pcbRead) 450 STDMETHODIMP WBPassthru::Read(/* [in, out] */ void *pv,/* [in] */ ULONG cb,/* [o ut] */ ULONG *pcbRead)
392 { 451 {
393 452 WBPassthruSink* pSink = GetSink();
394 WBPassthruSink* pSink = GetSink(); 453 return pSink->OnRead(pv, cb, pcbRead);
395 return pSink->Read(pv, cb, pcbRead); 454 }
396 } 455
456 STDMETHODIMP WBPassthru::LockRequest(/* [in] */ DWORD options)
457 {
458 if (!m_hasOriginalStartCalled)
459 {
460 return S_OK;
461 }
462 return BaseClass::LockRequest(options);
463 }
464
465 STDMETHODIMP WBPassthru::UnlockRequest()
466 {
467 if (!m_hasOriginalStartCalled)
468 {
469 return S_OK;
470 }
471 return BaseClass::UnlockRequest();
472 }
OLDNEW
« no previous file with comments | « src/plugin/PluginWbPassThrough.h ('k') | src/plugin/SinkPolicy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld