diff options
-rw-r--r-- | chrome_frame/bind_context_info.cc | 43 | ||||
-rw-r--r-- | chrome_frame/bind_context_info.h | 13 | ||||
-rw-r--r-- | chrome_frame/bind_status_callback_impl.cc | 7 | ||||
-rw-r--r-- | chrome_frame/chrome_active_document.cc | 4 | ||||
-rw-r--r-- | chrome_frame/urlmon_bind_status_callback.cc | 27 | ||||
-rw-r--r-- | chrome_frame/urlmon_bind_status_callback.h | 5 | ||||
-rw-r--r-- | chrome_frame/urlmon_moniker.cc | 20 | ||||
-rw-r--r-- | chrome_frame/urlmon_url_request.cc | 12 | ||||
-rw-r--r-- | chrome_frame/utils.h | 12 |
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_ |