1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome_frame/bind_status_callback_impl.h"
6
7#include "base/logging.h"
8#include "base/strings/string_util.h"
9#include "base/strings/stringprintf.h"
10#include "base/threading/platform_thread.h"
11
12BSCBImpl::BSCBImpl() {
13  DVLOG(1) << __FUNCTION__ << me();
14}
15
16BSCBImpl::~BSCBImpl() {
17  DVLOG(1) << __FUNCTION__ << me();
18}
19
20std::string BSCBImpl::me() {
21  return base::StringPrintf(" obj=0x%08X", static_cast<BSCBImpl*>(this));
22}
23
24HRESULT BSCBImpl::DelegateQI(void* obj, REFIID iid, void** ret, DWORD cookie) {
25  BSCBImpl* me = reinterpret_cast<BSCBImpl*>(obj);
26  HRESULT hr = E_NOINTERFACE;
27  if (me->delegate_)
28    hr = me->delegate_.QueryInterface(iid, ret);
29  return hr;
30}
31
32void BSCBImpl::Initialize(IBindStatusCallback* original) {
33  DCHECK(!delegate_);
34  delegate_ = original;
35}
36
37HRESULT BSCBImpl::AttachToBind(IBindCtx* bind_ctx) {
38  HRESULT hr = S_OK;
39  hr = ::RegisterBindStatusCallback(bind_ctx, this, delegate_.Receive(), 0);
40  if (SUCCEEDED(hr)) {
41    bind_ctx_ = bind_ctx;
42  }
43
44  return hr;
45}
46
47HRESULT BSCBImpl::ReleaseBind() {
48  // AddRef ourselves while we release these objects as we might
49  // perish during this operation.
50  AddRef();
51
52  HRESULT hr = S_OK;
53  if (bind_ctx_) {
54    hr = ::RevokeBindStatusCallback(bind_ctx_, this);
55  }
56  delegate_.Release();
57  bind_ctx_.Release();
58
59  Release();
60
61  return hr;
62}
63
64// IServiceProvider
65HRESULT BSCBImpl::QueryService(REFGUID service, REFIID iid, void** object) {
66  HRESULT hr = E_NOINTERFACE;
67  if (delegate_) {
68    base::win::ScopedComPtr<IServiceProvider> svc;
69    svc.QueryFrom(delegate_);
70    if (svc) {
71      hr = svc->QueryService(service, iid, object);
72    }
73  }
74  return hr;
75}
76
77// IBindStatusCallback
78HRESULT BSCBImpl::OnStartBinding(DWORD reserved, IBinding* binding) {
79  DVLOG(1) << __FUNCTION__ << me()
80           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
81  HRESULT hr = S_OK;
82  if (delegate_)
83    hr = delegate_->OnStartBinding(reserved, binding);
84  return hr;
85}
86
87HRESULT BSCBImpl::GetPriority(LONG* priority) {
88  DVLOG(1) << __FUNCTION__ << me()
89           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
90  HRESULT hr = S_OK;
91  if (delegate_)
92    hr = delegate_->GetPriority(priority);
93  return hr;
94}
95
96HRESULT BSCBImpl::OnLowResource(DWORD reserved) {
97  DVLOG(1) << __FUNCTION__ << me()
98           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
99  HRESULT hr = S_OK;
100  if (delegate_)
101    hr = delegate_->OnLowResource(reserved);
102  return hr;
103}
104
105HRESULT BSCBImpl::OnProgress(ULONG progress, ULONG progress_max,
106                              ULONG status_code, LPCWSTR status_text) {
107  DVLOG(1) << __FUNCTION__ << me()
108           << base::StringPrintf(" status=%i tid=%i %ls", status_code,
109                                 base::PlatformThread::CurrentId(),
110                                 status_text);
111  HRESULT hr = S_OK;
112  if (delegate_)
113    delegate_->OnProgress(progress, progress_max, status_code, status_text);
114  return hr;
115}
116
117HRESULT BSCBImpl::OnStopBinding(HRESULT hresult, LPCWSTR error) {
118  DVLOG(1) << __FUNCTION__ << me()
119           << base::StringPrintf(" hr=0x%08X '%ls' tid=%i", hresult, error,
120                                 base::PlatformThread::CurrentId());
121  HRESULT hr = S_OK;
122  if (delegate_)
123    delegate_->OnStopBinding(hresult, error);
124  return hr;
125}
126
127HRESULT BSCBImpl::GetBindInfo(DWORD* bindf, BINDINFO* bind_info) {
128  DVLOG(1) << __FUNCTION__ << me()
129           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
130  HRESULT hr = S_OK;
131  if (delegate_)
132    delegate_->GetBindInfo(bindf, bind_info);
133  return hr;
134}
135
136HRESULT BSCBImpl::OnDataAvailable(DWORD bscf, DWORD size,
137                                   FORMATETC* format_etc, STGMEDIUM* stgmed) {
138  DVLOG(1) << __FUNCTION__ << me()
139           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
140  HRESULT hr = S_OK;
141  if (delegate_)
142    hr = delegate_->OnDataAvailable(bscf, size, format_etc, stgmed);
143  return hr;
144}
145
146HRESULT BSCBImpl::OnObjectAvailable(REFIID iid, IUnknown* unk) {
147  DVLOG(1) << __FUNCTION__ << me()
148           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
149  HRESULT hr = S_OK;
150  if (delegate_)
151    delegate_->OnObjectAvailable(iid, unk);
152  return hr;
153}
154
155// IBindStatusCallbackEx
156HRESULT BSCBImpl::GetBindInfoEx(DWORD* bindf, BINDINFO* bind_info,
157                                DWORD* bindf2, DWORD* reserved) {
158  DVLOG(1) << __FUNCTION__ << me()
159           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
160  HRESULT hr = S_OK;
161  if (delegate_) {
162    base::win::ScopedComPtr<IBindStatusCallbackEx> bscbex;
163    bscbex.QueryFrom(delegate_);
164    if (bscbex)
165      hr = bscbex->GetBindInfoEx(bindf, bind_info, bindf2, reserved);
166  }
167  return hr;
168}
169
170HRESULT BSCBImpl::BeginningTransaction(LPCWSTR url, LPCWSTR headers,
171                                       DWORD reserved,
172                                       LPWSTR* additional_headers) {
173  DVLOG(1) << __FUNCTION__ << me()
174           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
175
176  HRESULT hr = S_OK;
177  if (delegate_) {
178    base::win::ScopedComPtr<IHttpNegotiate> http_negotiate;
179    http_negotiate.QueryFrom(delegate_);
180    if (http_negotiate) {
181      hr = http_negotiate->BeginningTransaction(url, headers, reserved,
182                                                additional_headers);
183    }
184  }
185
186  DLOG_IF(ERROR, FAILED(hr)) << __FUNCTION__;
187  return hr;
188}
189
190HRESULT BSCBImpl::OnResponse(DWORD response_code, LPCWSTR response_headers,
191                             LPCWSTR request_headers,
192                             LPWSTR* additional_headers) {
193  DVLOG(1) << __FUNCTION__ << me()
194           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
195
196  HRESULT hr = S_OK;
197  if (delegate_) {
198    base::win::ScopedComPtr<IHttpNegotiate> http_negotiate;
199    http_negotiate.QueryFrom(delegate_);
200    if (http_negotiate) {
201      hr = http_negotiate->OnResponse(response_code, response_headers,
202                                      request_headers, additional_headers);
203    }
204  }
205  return hr;
206}
207
208HRESULT BSCBImpl::GetRootSecurityId(BYTE* security_id, DWORD* security_id_size,
209                                    DWORD_PTR reserved) {
210  HRESULT hr = S_OK;
211  if (delegate_) {
212    base::win::ScopedComPtr<IHttpNegotiate2> http_negotiate;
213    http_negotiate.QueryFrom(delegate_);
214    if (http_negotiate) {
215      hr = http_negotiate->GetRootSecurityId(security_id, security_id_size,
216                                             reserved);
217    }
218  }
219  return hr;
220}
221
222HRESULT BSCBImpl::GetSerializedClientCertContext(BYTE** cert,
223                                                 DWORD* cert_size) {
224  HRESULT hr = S_OK;
225  if (delegate_) {
226    base::win::ScopedComPtr<IHttpNegotiate3> http_negotiate;
227    http_negotiate.QueryFrom(delegate_);
228    if (http_negotiate) {
229      return http_negotiate->GetSerializedClientCertContext(cert, cert_size);
230    }
231  }
232  return hr;
233}
234