// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome_frame/bind_status_callback_impl.h"

#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/platform_thread.h"

BSCBImpl::BSCBImpl() {
  DVLOG(1) << __FUNCTION__ << me();
}

BSCBImpl::~BSCBImpl() {
  DVLOG(1) << __FUNCTION__ << me();
}

std::string BSCBImpl::me() {
  return base::StringPrintf(" obj=0x%08X", static_cast<BSCBImpl*>(this));
}

HRESULT BSCBImpl::DelegateQI(void* obj, REFIID iid, void** ret, DWORD cookie) {
  BSCBImpl* me = reinterpret_cast<BSCBImpl*>(obj);
  HRESULT hr = E_NOINTERFACE;
  if (me->delegate_)
    hr = me->delegate_.QueryInterface(iid, ret);
  return hr;
}

void BSCBImpl::Initialize(IBindStatusCallback* original) {
  DCHECK(!delegate_);
  delegate_ = original;
}

HRESULT BSCBImpl::AttachToBind(IBindCtx* bind_ctx) {
  HRESULT hr = S_OK;
  hr = ::RegisterBindStatusCallback(bind_ctx, this, delegate_.Receive(), 0);
  if (SUCCEEDED(hr)) {
    bind_ctx_ = bind_ctx;
  }

  return hr;
}

HRESULT BSCBImpl::ReleaseBind() {
  // AddRef ourselves while we release these objects as we might
  // perish during this operation.
  AddRef();

  HRESULT hr = S_OK;
  if (bind_ctx_) {
    hr = ::RevokeBindStatusCallback(bind_ctx_, this);
  }
  delegate_.Release();
  bind_ctx_.Release();

  Release();

  return hr;
}

// IServiceProvider
HRESULT BSCBImpl::QueryService(REFGUID service, REFIID iid, void** object) {
  HRESULT hr = E_NOINTERFACE;
  if (delegate_) {
    base::win::ScopedComPtr<IServiceProvider> svc;
    svc.QueryFrom(delegate_);
    if (svc) {
      hr = svc->QueryService(service, iid, object);
    }
  }
  return hr;
}

// IBindStatusCallback
HRESULT BSCBImpl::OnStartBinding(DWORD reserved, IBinding* binding) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
  HRESULT hr = S_OK;
  if (delegate_)
    hr = delegate_->OnStartBinding(reserved, binding);
  return hr;
}

HRESULT BSCBImpl::GetPriority(LONG* priority) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
  HRESULT hr = S_OK;
  if (delegate_)
    hr = delegate_->GetPriority(priority);
  return hr;
}

HRESULT BSCBImpl::OnLowResource(DWORD reserved) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
  HRESULT hr = S_OK;
  if (delegate_)
    hr = delegate_->OnLowResource(reserved);
  return hr;
}

HRESULT BSCBImpl::OnProgress(ULONG progress, ULONG progress_max,
                              ULONG status_code, LPCWSTR status_text) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" status=%i tid=%i %ls", status_code,
                                 base::PlatformThread::CurrentId(),
                                 status_text);
  HRESULT hr = S_OK;
  if (delegate_)
    delegate_->OnProgress(progress, progress_max, status_code, status_text);
  return hr;
}

HRESULT BSCBImpl::OnStopBinding(HRESULT hresult, LPCWSTR error) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" hr=0x%08X '%ls' tid=%i", hresult, error,
                                 base::PlatformThread::CurrentId());
  HRESULT hr = S_OK;
  if (delegate_)
    delegate_->OnStopBinding(hresult, error);
  return hr;
}

HRESULT BSCBImpl::GetBindInfo(DWORD* bindf, BINDINFO* bind_info) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
  HRESULT hr = S_OK;
  if (delegate_)
    delegate_->GetBindInfo(bindf, bind_info);
  return hr;
}

HRESULT BSCBImpl::OnDataAvailable(DWORD bscf, DWORD size,
                                   FORMATETC* format_etc, STGMEDIUM* stgmed) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
  HRESULT hr = S_OK;
  if (delegate_)
    hr = delegate_->OnDataAvailable(bscf, size, format_etc, stgmed);
  return hr;
}

HRESULT BSCBImpl::OnObjectAvailable(REFIID iid, IUnknown* unk) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
  HRESULT hr = S_OK;
  if (delegate_)
    delegate_->OnObjectAvailable(iid, unk);
  return hr;
}

// IBindStatusCallbackEx
HRESULT BSCBImpl::GetBindInfoEx(DWORD* bindf, BINDINFO* bind_info,
                                DWORD* bindf2, DWORD* reserved) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());
  HRESULT hr = S_OK;
  if (delegate_) {
    base::win::ScopedComPtr<IBindStatusCallbackEx> bscbex;
    bscbex.QueryFrom(delegate_);
    if (bscbex)
      hr = bscbex->GetBindInfoEx(bindf, bind_info, bindf2, reserved);
  }
  return hr;
}

HRESULT BSCBImpl::BeginningTransaction(LPCWSTR url, LPCWSTR headers,
                                       DWORD reserved,
                                       LPWSTR* additional_headers) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());

  HRESULT hr = S_OK;
  if (delegate_) {
    base::win::ScopedComPtr<IHttpNegotiate> http_negotiate;
    http_negotiate.QueryFrom(delegate_);
    if (http_negotiate) {
      hr = http_negotiate->BeginningTransaction(url, headers, reserved,
                                                additional_headers);
    }
  }

  DLOG_IF(ERROR, FAILED(hr)) << __FUNCTION__;
  return hr;
}

HRESULT BSCBImpl::OnResponse(DWORD response_code, LPCWSTR response_headers,
                             LPCWSTR request_headers,
                             LPWSTR* additional_headers) {
  DVLOG(1) << __FUNCTION__ << me()
           << base::StringPrintf(" tid=%i", base::PlatformThread::CurrentId());

  HRESULT hr = S_OK;
  if (delegate_) {
    base::win::ScopedComPtr<IHttpNegotiate> http_negotiate;
    http_negotiate.QueryFrom(delegate_);
    if (http_negotiate) {
      hr = http_negotiate->OnResponse(response_code, response_headers,
                                      request_headers, additional_headers);
    }
  }
  return hr;
}

HRESULT BSCBImpl::GetRootSecurityId(BYTE* security_id, DWORD* security_id_size,
                                    DWORD_PTR reserved) {
  HRESULT hr = S_OK;
  if (delegate_) {
    base::win::ScopedComPtr<IHttpNegotiate2> http_negotiate;
    http_negotiate.QueryFrom(delegate_);
    if (http_negotiate) {
      hr = http_negotiate->GetRootSecurityId(security_id, security_id_size,
                                             reserved);
    }
  }
  return hr;
}

HRESULT BSCBImpl::GetSerializedClientCertContext(BYTE** cert,
                                                 DWORD* cert_size) {
  HRESULT hr = S_OK;
  if (delegate_) {
    base::win::ScopedComPtr<IHttpNegotiate3> http_negotiate;
    http_negotiate.QueryFrom(delegate_);
    if (http_negotiate) {
      return http_negotiate->GetSerializedClientCertContext(cert, cert_size);
    }
  }
  return hr;
}
