summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome_frame/bind_context_info.cc43
-rw-r--r--chrome_frame/bind_context_info.h13
-rw-r--r--chrome_frame/bind_status_callback_impl.cc7
-rw-r--r--chrome_frame/chrome_active_document.cc4
-rw-r--r--chrome_frame/urlmon_bind_status_callback.cc27
-rw-r--r--chrome_frame/urlmon_bind_status_callback.h5
-rw-r--r--chrome_frame/urlmon_moniker.cc20
-rw-r--r--chrome_frame/urlmon_url_request.cc12
-rw-r--r--chrome_frame/utils.h12
9 files changed, 89 insertions, 54 deletions
diff --git a/chrome_frame/bind_context_info.cc b/chrome_frame/bind_context_info.cc
index 07ba1f3..fdc6c8d 100644
--- a/chrome_frame/bind_context_info.cc
+++ b/chrome_frame/bind_context_info.cc
@@ -31,41 +31,46 @@ HRESULT BindContextInfo::Initialize(IBindCtx* bind_ctx) {
return hr;
}
-BindContextInfo* BindContextInfo::FromBindContext(IBindCtx* bind_context) {
+HRESULT BindContextInfo::FromBindContext(IBindCtx* bind_context,
+ BindContextInfo** info) {
+ DCHECK(info);
if (!bind_context) {
NOTREACHED();
- return NULL;
+ return E_POINTER;
}
ScopedComPtr<IUnknown> context;
- bind_context->GetObjectParam(kBindContextInfo, context.Receive());
+ HRESULT hr = bind_context->GetObjectParam(kBindContextInfo,
+ context.Receive());
if (context) {
ScopedComPtr<IBindContextInfoInternal> internal;
- HRESULT hr = internal.QueryFrom(context);
+ hr = internal.QueryFrom(context);
DCHECK(SUCCEEDED(hr));
if (SUCCEEDED(hr)) {
BindContextInfo* ret = NULL;
- internal->GetCppObject(reinterpret_cast<void**>(&ret));
- DCHECK(ret);
+ hr = internal->GetCppObject(reinterpret_cast<void**>(info));
+ DCHECK_EQ(hr, S_OK);
DLOG_IF(ERROR, reinterpret_cast<void*>(ret) !=
reinterpret_cast<void*>(internal.get()))
<< "marshalling took place!";
- return ret;
+ }
+ } else {
+ DCHECK(FAILED(hr));
+ CComObject<BindContextInfo>* bind_context_info = NULL;
+ hr = CComObject<BindContextInfo>::CreateInstance(&bind_context_info);
+ DCHECK(bind_context_info != NULL);
+ if (bind_context_info) {
+ bind_context_info->AddRef();
+ hr = bind_context_info->Initialize(bind_context);
+ if (FAILED(hr)) {
+ bind_context_info->Release();
+ } else {
+ *info = bind_context_info;
+ }
}
}
- CComObject<BindContextInfo>* bind_context_info = NULL;
- HRESULT hr = CComObject<BindContextInfo>::CreateInstance(&bind_context_info);
- DCHECK(bind_context_info != NULL);
- if (bind_context_info) {
- bind_context_info->AddRef();
- hr = bind_context_info->Initialize(bind_context);
- bind_context_info->Release();
- if (FAILED(hr))
- bind_context_info = NULL;
- }
-
- return bind_context_info;
+ return hr;
}
void BindContextInfo::SetToSwitch(IStream* cache) {
diff --git a/chrome_frame/bind_context_info.h b/chrome_frame/bind_context_info.h
index d41c440..07ec284 100644
--- a/chrome_frame/bind_context_info.h
+++ b/chrome_frame/bind_context_info.h
@@ -19,9 +19,10 @@ IBindContextInfoInternal : public IUnknown {
// This class maintains contextual information used by ChromeFrame.
// This information is maintained in the bind context.
-class BindContextInfo
- : public IBindContextInfoInternal,
- public CComObjectRoot {
+// Association with GUID_NULL is for convenience.
+class __declspec(uuid("00000000-0000-0000-0000-000000000000")) BindContextInfo
+ : public CComObjectRootEx<CComMultiThreadModel>,
+ public IBindContextInfoInternal {
public:
BindContextInfo();
~BindContextInfo();
@@ -33,7 +34,10 @@ class BindContextInfo
// Returns the BindContextInfo instance associated with the bind
// context. Creates it if needed.
- static BindContextInfo* FromBindContext(IBindCtx* bind_context);
+ // The returned info object will be AddRef-ed on return, so use
+ // ScopedComPtr<>::Receive() to receive this pointer.
+ static HRESULT FromBindContext(IBindCtx* bind_context,
+ BindContextInfo** info);
void set_chrome_request(bool chrome_request) {
chrome_request_ = chrome_request;
@@ -79,6 +83,7 @@ class BindContextInfo
protected:
STDMETHOD(GetCppObject)(void** me) {
DCHECK(me);
+ AddRef();
*me = static_cast<BindContextInfo*>(this);
return S_OK;
}
diff --git a/chrome_frame/bind_status_callback_impl.cc b/chrome_frame/bind_status_callback_impl.cc
index 91a8424..3b7ff04 100644
--- a/chrome_frame/bind_status_callback_impl.cc
+++ b/chrome_frame/bind_status_callback_impl.cc
@@ -44,12 +44,19 @@ HRESULT BSCBImpl::AttachToBind(IBindCtx* bind_ctx) {
}
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;
}
diff --git a/chrome_frame/chrome_active_document.cc b/chrome_frame/chrome_active_document.cc
index 19a42a8..aa8b07a 100644
--- a/chrome_frame/chrome_active_document.cc
+++ b/chrome_frame/chrome_active_document.cc
@@ -242,8 +242,8 @@ STDMETHODIMP ChromeActiveDocument::Load(BOOL fully_avalable,
std::wstring url;
- scoped_refptr<BindContextInfo> info =
- BindContextInfo::FromBindContext(bind_context);
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(bind_context, info.Receive());
DCHECK(info);
if (info && !info->url().empty()) {
url = info->url();
diff --git a/chrome_frame/urlmon_bind_status_callback.cc b/chrome_frame/urlmon_bind_status_callback.cc
index 0f886a1..3483917 100644
--- a/chrome_frame/urlmon_bind_status_callback.cc
+++ b/chrome_frame/urlmon_bind_status_callback.cc
@@ -208,10 +208,8 @@ BSCBStorageBind::BSCBStorageBind() : clip_format_(CF_NULL) {
}
BSCBStorageBind::~BSCBStorageBind() {
- for (std::vector<Progress*>::iterator i = saved_progress_.begin();
- i != saved_progress_.end(); i++) {
- delete (*i);
- }
+ std::for_each(saved_progress_.begin(), saved_progress_.end(),
+ utils::DeleteObject());
}
HRESULT BSCBStorageBind::Initialize(IMoniker* moniker, IBindCtx* bind_ctx) {
@@ -252,8 +250,8 @@ STDMETHODIMP BSCBStorageBind::OnProgress(ULONG progress, ULONG progress_max,
// Remember the last redirected URL in case we get switched into
// chrome frame
if (status_code == BINDSTATUS_REDIRECTING) {
- scoped_refptr<BindContextInfo> info =
- BindContextInfo::FromBindContext(bind_ctx_);
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(bind_ctx_, info.Receive());
DCHECK(info);
if (info)
info->set_url(status_text);
@@ -356,12 +354,17 @@ HRESULT BSCBStorageBind::MayPlayBack(DWORD flags) {
clip_format_ = kMagicClipFormat;
} else {
if (!saved_progress_.empty()) {
- for (std::vector<Progress*>::iterator i = saved_progress_.begin();
+ for (ProgressVector::iterator i = saved_progress_.begin();
i != saved_progress_.end(); i++) {
Progress* p = (*i);
- CallbackImpl::OnProgress(p->progress(), p->progress_max(),
- p->status_code(), p->status_text());
- delete p;
+ // We don't really expect a race condition here but just for sake
+ // of completeness we check.
+ if (p) {
+ (*i) = NULL;
+ CallbackImpl::OnProgress(p->progress(), p->progress_max(),
+ p->status_code(), p->status_text());
+ delete p;
+ }
}
saved_progress_.clear();
}
@@ -369,8 +372,8 @@ HRESULT BSCBStorageBind::MayPlayBack(DWORD flags) {
if (data_sniffer_.is_cache_valid()) {
if (data_sniffer_.is_chrome()) {
- scoped_refptr<BindContextInfo> info =
- BindContextInfo::FromBindContext(bind_ctx_);
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(bind_ctx_, info.Receive());
DCHECK(info);
if (info) {
info->SetToSwitch(data_sniffer_.cache_);
diff --git a/chrome_frame/urlmon_bind_status_callback.h b/chrome_frame/urlmon_bind_status_callback.h
index ef73cb8..98b258a 100644
--- a/chrome_frame/urlmon_bind_status_callback.h
+++ b/chrome_frame/urlmon_bind_status_callback.h
@@ -131,7 +131,7 @@ END_COM_MAP()
int len = lstrlenW(status_text) + 1;
status_text_.reset(new wchar_t[len]);
if (status_text_.get()) {
- lstrcpyW(status_text_.get(), status_text);
+ lstrcpynW(status_text_.get(), status_text, len);
} else {
NOTREACHED();
}
@@ -167,7 +167,8 @@ END_COM_MAP()
scoped_ptr<wchar_t> status_text_;
};
- std::vector<Progress*> saved_progress_;
+ typedef std::vector<Progress*> ProgressVector;
+ ProgressVector saved_progress_;
CLIPFORMAT clip_format_;
private:
diff --git a/chrome_frame/urlmon_moniker.cc b/chrome_frame/urlmon_moniker.cc
index 44decb3..3030128 100644
--- a/chrome_frame/urlmon_moniker.cc
+++ b/chrome_frame/urlmon_moniker.cc
@@ -130,8 +130,8 @@ bool ShouldWrapCallback(IMoniker* moniker, REFIID iid, IBindCtx* bind_context) {
return false;
}
- scoped_refptr<BindContextInfo> info =
- BindContextInfo::FromBindContext(bind_context);
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(bind_context, info.Receive());
DCHECK(info);
if (info && info->chrome_request()) {
DLOG(INFO) << __FUNCTION__ << " Url: " << url <<
@@ -179,8 +179,8 @@ HRESULT MonikerPatch::BindToObject(IMoniker_BindToObject_Fn original,
HRESULT hr = S_OK;
// Bind context is marked for switch when we sniff data in BSCBStorageBind
// and determine that the renderer to be used is Chrome.
- scoped_refptr<BindContextInfo> info =
- BindContextInfo::FromBindContext(bind_ctx);
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(bind_ctx, info.Receive());
DCHECK(info);
if (info) {
if (info->is_switching()) {
@@ -188,7 +188,7 @@ HRESULT MonikerPatch::BindToObject(IMoniker_BindToObject_Fn original,
// simply register Chrome Frame ActiveDoc as a handler for 'text/html'
// in this bind context. This makes urlmon instantiate CF Active doc
// instead of mshtml.
- char* media_types[] = { "text/html" };
+ const char* media_types[] = { "text/html" };
CLSID classes[] = { CLSID_ChromeActiveDocument };
hr = RegisterMediaTypeClass(bind_ctx, arraysize(media_types), media_types,
classes, 0);
@@ -213,22 +213,24 @@ HRESULT MonikerPatch::BindToStorage(IMoniker_BindToStorage_Fn original,
ExceptionBarrierReportOnlyModule barrier;
HRESULT hr = S_OK;
+ scoped_refptr<BSCBStorageBind> auto_release_callback;
CComObject<BSCBStorageBind>* callback = NULL;
if (ShouldWrapCallback(me, iid, bind_ctx)) {
hr = CComObject<BSCBStorageBind>::CreateInstance(&callback);
- callback->AddRef();
+ auto_release_callback = callback;
+ DCHECK_EQ(callback->m_dwRef, 1);
hr = callback->Initialize(me, bind_ctx);
DCHECK(SUCCEEDED(hr));
- hr = original(me, bind_ctx, to_left, iid, obj);
- } else {
- hr = original(me, bind_ctx, to_left, iid, obj);
}
+ hr = original(me, bind_ctx, to_left, iid, obj);
+
// If the binding terminates before the data could be played back
// now is the chance. Sometimes OnStopBinding happens after this returns
// and then it's too late.
if ((S_OK == hr) && callback)
callback->MayPlayBack(BSCF_LASTDATANOTIFICATION);
+
return hr;
}
diff --git a/chrome_frame/urlmon_url_request.cc b/chrome_frame/urlmon_url_request.cc
index f767ab1..90aff6c1 100644
--- a/chrome_frame/urlmon_url_request.cc
+++ b/chrome_frame/urlmon_url_request.cc
@@ -304,8 +304,8 @@ STDMETHODIMP UrlmonUrlRequest::OnProgress(ULONG progress, ULONG max_progress,
// If we receive a redirect for the initial pending request initiated
// when our document loads we should stash it away and inform Chrome
// accordingly when it requests data for the original URL.
- scoped_refptr<BindContextInfo> info =
- BindContextInfo::FromBindContext(bind_context_);
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(bind_context_, info.Receive());
DCHECK(info);
GURL previously_redirected(info ? info->url() : std::wstring());
if (GURL(status_text) != previously_redirected) {
@@ -789,8 +789,8 @@ HRESULT UrlmonUrlRequest::StartAsyncDownload() {
ScopedComPtr<IHttpSecurity> self(this);
// Inform our moniker patch this binding should not be tortured.
- scoped_refptr<BindContextInfo> info =
- BindContextInfo::FromBindContext(bind_context_);
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(bind_context_, info.Receive());
DCHECK(info);
if (info)
info->set_chrome_request(true);
@@ -918,8 +918,8 @@ void UrlmonUrlRequestManager::SetInfoForUrl(const std::wstring& url,
DCHECK(start_url.is_valid());
DCHECK(pending_request_ == NULL);
- scoped_refptr<BindContextInfo> info =
- BindContextInfo::FromBindContext(bind_ctx);
+ ScopedComPtr<BindContextInfo> info;
+ BindContextInfo::FromBindContext(bind_ctx, info.Receive());
DCHECK(info);
IStream* cache = info ? info->cache() : NULL;
pending_request_ = new_request;
diff --git a/chrome_frame/utils.h b/chrome_frame/utils.h
index ab4a3cb..d0f64d5 100644
--- a/chrome_frame/utils.h
+++ b/chrome_frame/utils.h
@@ -439,4 +439,16 @@ ProtocolPatchMethod GetPatchMethod();
// Returns true if the IMoniker patch is enabled.
bool MonikerPatchEnabled();
+// STL helper class that implements a functor to delete objects.
+// E.g: std::for_each(v.begin(), v.end(), utils::DeleteObject());
+namespace utils {
+class DeleteObject {
+ public:
+ template <typename T>
+ void operator()(T* obj) {
+ delete obj;
+ }
+};
+}
+
#endif // CHROME_FRAME_UTILS_H_