Index: chrome_frame/protocol_sink_wrap.cc |
=================================================================== |
--- chrome_frame/protocol_sink_wrap.cc (revision 52494) |
+++ chrome_frame/protocol_sink_wrap.cc (working copy) |
@@ -91,6 +91,48 @@ |
return ScopedComPtr<IInternetProtocolSink>(new_sink); |
} |
+HRESULT ProtocolSinkWrap::ObtainServiceProvider() { |
+ HRESULT hr = S_OK; |
+ if (!delegate_service_provider_) { |
+ hr = delegate_service_provider_.QueryFrom(delegate_); |
+ } |
+ return hr; |
+} |
+ |
+HRESULT ProtocolSinkWrap::ObtainHttpNegotiate() { |
+ if (UserAgentAddOn::has_delegate()) |
+ return S_OK; |
+ |
+ HRESULT hr = ObtainServiceProvider(); |
+ if (hr == S_OK) { |
+ ScopedComPtr<IHttpNegotiate> http_negotiate; |
+ hr = delegate_service_provider_->QueryService( |
+ IID_IHttpNegotiate, |
+ IID_IHttpNegotiate, |
+ reinterpret_cast<void**>(http_negotiate.Receive())); |
+ UserAgentAddOn::set_delegate(http_negotiate); |
+ } |
+ return hr; |
+} |
+ |
+STDMETHODIMP ProtocolSinkWrap::QueryService(REFGUID guidService, REFIID riid, |
+ void** ppvObject) { |
+ // We really insist to append "chromeframe" user-agent header, even in the |
+ // very unlikely case when delegate does not support IServiceProvider and/or |
+ // IHttpNegotiate. |
+ if (guidService == IID_IHttpNegotiate && riid == IID_IHttpNegotiate) { |
+ ObtainHttpNegotiate(); |
+ AddRef(); |
+ *ppvObject = reinterpret_cast<void**>(static_cast<IHttpNegotiate*>(this)); |
+ return S_OK; |
+ } |
+ |
+ HRESULT hr = ObtainServiceProvider(); |
+ if (hr == S_OK) |
+ hr = delegate_service_provider_->QueryService(guidService, riid, ppvObject); |
+ return hr; |
+} |
+ |
// IInternetProtocolSink methods |
STDMETHODIMP ProtocolSinkWrap::Switch(PROTOCOLDATA* protocol_data) { |
HRESULT hr = E_FAIL; |
@@ -318,18 +360,27 @@ |
// TODO(stoyan): BINDSTATUS_RAWMIMETYPE |
case BINDSTATUS_MIMETYPEAVAILABLE: |
case BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE: |
- SaveSuggestedMimeType(status_text); |
+ // When Transaction is attached i.e. when existing BTS it terminated |
+ // and "converted" to BTO, events will be re-fired for the new sink, |
+ // but we may skip the renderer_type_ determination since it's already |
+ // done. |
+ if (renderer_type_ == UNDETERMINED) { |
+ SaveSuggestedMimeType(status_text); |
+ // This may seem awkward. CBinding's implementation of IWinInetHttpInfo |
+ // will forward to CTransaction that will forward to the real protocol. |
+ // We may ask CTransaction (our protocol_ member) for IWinInetHttpInfo. |
+ ScopedComPtr<IWinInetHttpInfo> info; |
+ info.QueryFrom(delegate); |
+ renderer_type_ = DetermineRendererTypeFromMetaData(suggested_mime_type_, |
+ url_, info); |
+ } |
- ScopedComPtr<IWinInetHttpInfo> info; |
- info.QueryFrom(delegate); |
- renderer_type_ = DetermineRendererTypeFromMetaData(suggested_mime_type_, |
- url_, info); |
- |
if (renderer_type_ == CHROME) { |
// Suggested mime type is "text/html" and we either have OptInUrl |
// or X-UA-Compatible HTTP headers. |
DLOG(INFO) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE " |
<< kChromeMimeType; |
+ SaveReferrer(delegate); |
delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType); |
} else if (renderer_type_ == OTHER) { |
// Suggested mime type is not "text/html" - we are not interested in |
@@ -369,6 +420,7 @@ |
if (renderer_type_ == CHROME) { |
DLOG(INFO) << "Forwarding BINDSTATUS_MIMETYPEAVAILABLE " |
<< kChromeMimeType; |
+ SaveReferrer(delegate); |
delegate->ReportProgress(BINDSTATUS_MIMETYPEAVAILABLE, kChromeMimeType); |
} |
@@ -446,6 +498,23 @@ |
} |
} |
+void ProtData::SaveReferrer(IInternetProtocolSink* delegate) { |
+ DCHECK_EQ(CHROME, renderer_type_); |
+ ScopedComPtr<IWinInetHttpInfo> info; |
+ info.QueryFrom(delegate); |
+ DCHECK(info); |
+ if (info) { |
+ char buffer[4096] = {0}; |
+ DWORD len = sizeof(buffer); |
+ DWORD flags = 0; |
+ HRESULT hr = info->QueryInfo( |
+ HTTP_QUERY_REFERER | HTTP_QUERY_FLAG_REQUEST_HEADERS, |
+ buffer, &len, &flags, 0); |
+ if (hr == S_OK && len > 0) |
+ referrer_.assign(buffer); |
+ } |
+} |
+ |
scoped_refptr<ProtData> ProtData::DataFromProtocol( |
IInternetProtocol* protocol) { |
scoped_refptr<ProtData> instance; |