summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome_frame/urlmon_url_request.cc53
-rw-r--r--chrome_frame/urlmon_url_request.h5
-rw-r--r--chrome_frame/urlmon_url_request_private.h10
3 files changed, 49 insertions, 19 deletions
diff --git a/chrome_frame/urlmon_url_request.cc b/chrome_frame/urlmon_url_request.cc
index 2a1d28d..fb937bf 100644
--- a/chrome_frame/urlmon_url_request.cc
+++ b/chrome_frame/urlmon_url_request.cc
@@ -138,13 +138,21 @@ HRESULT UrlmonUrlRequest::InitPending(const GURL& url, IMoniker* moniker,
return S_OK;
}
-void UrlmonUrlRequest::StealMoniker(IMoniker** moniker, IBindCtx** bctx) {
- // Could be called in any thread. There should be no race
- // since moniker_ is not released while we are in manager's request map.
+void UrlmonUrlRequest::TerminateBind(TerminateBindCallback* callback) {
+ DCHECK_EQ(thread_, PlatformThread::CurrentId());
DLOG(INFO) << __FUNCTION__ << " id: " << id();
- DLOG_IF(WARNING, moniker == NULL) << __FUNCTION__ << " no moniker";
- *moniker = moniker_.Detach();
- *bctx = bind_context_.Detach();
+
+ if (status_.get_state() == Status::DONE) {
+ // Binding is stopped. Note result could be an error.
+ callback->Run(moniker_, bind_context_);
+ delete callback;
+ } else {
+ // WORKING (ABORTING?). Save the callback.
+ // Now we will return INET_TERMINATE_BIND from ::OnDataAvailable() and in
+ // ::OnStopBinding will invoke the callback passing our moniker and
+ // bind context.
+ terminate_bind_callback_.reset(callback);
+ }
}
size_t UrlmonUrlRequest::SendDataToDelegate(size_t bytes_to_read) {
@@ -272,6 +280,10 @@ STDMETHODIMP UrlmonUrlRequest::OnStopBinding(HRESULT result, LPCWSTR error) {
// Mark we a are done.
status_.Done();
+ if (result == INET_E_TERMINATED_BIND && terminate_requested()) {
+ terminate_bind_callback_->Run(moniker_, bind_context_);
+ }
+
// We always return INET_E_TERMINATED_BIND from OnDataAvailable
if (result == INET_E_TERMINATED_BIND)
result = S_OK;
@@ -396,6 +408,9 @@ STDMETHODIMP UrlmonUrlRequest::OnDataAvailable(DWORD flags, DWORD size,
DLOG(INFO) << StringPrintf("URL: %s Obj: %X - Bytes available: %d",
url().c_str(), this, size);
+ if (terminate_requested())
+ return INET_E_TERMINATED_BIND;
+
if (!storage || (storage->tymed != TYMED_ISTREAM)) {
NOTREACHED();
return E_INVALIDARG;
@@ -1025,18 +1040,9 @@ void UrlmonUrlRequestManager::DownloadRequestInHost(int request_id) {
if (IsWindow(notification_window_)) {
scoped_refptr<UrlmonUrlRequest> request(LookupRequest(request_id));
if (request) {
- ScopedComPtr<IMoniker> moniker;
- ScopedComPtr<IBindCtx> bind_context;
- request->StealMoniker(moniker.Receive(), bind_context.Receive());
- DLOG_IF(ERROR, moniker == NULL) << __FUNCTION__ << " No moniker!";
- if (moniker) {
- // We use SendMessage and not PostMessage to make sure that if the
- // notification window does not handle the message we won't leak
- // the moniker.
- ::SendMessage(notification_window_, WM_DOWNLOAD_IN_HOST,
- reinterpret_cast<WPARAM>(bind_context.get()),
- reinterpret_cast<LPARAM>(moniker.get()));
- }
+ UrlmonUrlRequest::TerminateBindCallback* callback = NewCallback(this,
+ &UrlmonUrlRequestManager::BindTerminated);
+ request->TerminateBind(callback);
}
} else {
NOTREACHED()
@@ -1044,6 +1050,17 @@ void UrlmonUrlRequestManager::DownloadRequestInHost(int request_id) {
}
}
+void UrlmonUrlRequestManager::BindTerminated(IMoniker* moniker,
+ IBindCtx* bind_ctx) {
+ // We use SendMessage and not PostMessage to make sure that if the
+ // notification window does not handle the message we won't leak
+ // the moniker.
+ ::SendMessage(notification_window_, WM_DOWNLOAD_IN_HOST,
+ reinterpret_cast<WPARAM>(bind_ctx),
+ reinterpret_cast<LPARAM>(moniker));
+}
+
+
void UrlmonUrlRequestManager::GetCookiesForUrl(const GURL& url, int cookie_id) {
DWORD cookie_size = 0;
bool success = true;
diff --git a/chrome_frame/urlmon_url_request.h b/chrome_frame/urlmon_url_request.h
index 9ace8dc..676aa3b 100644
--- a/chrome_frame/urlmon_url_request.h
+++ b/chrome_frame/urlmon_url_request.h
@@ -101,6 +101,11 @@ class UrlmonUrlRequestManager
const std::string& cookie_string,
int cookie_id);
+ // This method is passed as a callback to UrlmonUrlRequest::TerminateBind.
+ // We simply forward moniker and bind_ctx to host ActiveX/ActiveDocument,
+ // so it may start NavigateWithBindContext.
+ void BindTerminated(IMoniker* moniker, IBindCtx* bind_ctx);
+
// Map for (request_id <-> UrlmonUrlRequest)
typedef std::map<int, scoped_refptr<UrlmonUrlRequest> > RequestMap;
RequestMap request_map_;
diff --git a/chrome_frame/urlmon_url_request_private.h b/chrome_frame/urlmon_url_request_private.h
index ad7aa5a..f8c3561 100644
--- a/chrome_frame/urlmon_url_request_private.h
+++ b/chrome_frame/urlmon_url_request_private.h
@@ -36,7 +36,10 @@ class UrlmonUrlRequest
HWND notification_window, IStream* cache);
// Used from "DownloadRequestInHost".
- void StealMoniker(IMoniker** moniker, IBindCtx** bctx);
+ // Callback will be invoked either right away (if operation is finished) or
+ // from inside ::OnStopBinding() when it is safe to reuse the bind_context.
+ typedef Callback2<IMoniker*, IBindCtx*>::Type TerminateBindCallback;
+ void TerminateBind(TerminateBindCallback* callback);
// Parent Window for UrlMon error dialogs
void set_parent_window(HWND parent_window) {
@@ -110,6 +113,10 @@ class UrlmonUrlRequest
return pending_;
}
+ bool terminate_requested() const {
+ return terminate_bind_callback_.get() != NULL;
+ }
+
std::string response_headers() {
return response_headers_;
}
@@ -271,6 +278,7 @@ class UrlmonUrlRequest
// Set to true if the ChromeFrame instance is running in privileged mode.
bool privileged_mode_;
bool pending_;
+ scoped_ptr<TerminateBindCallback> terminate_bind_callback_;
std::string response_headers_;
DISALLOW_COPY_AND_ASSIGN(UrlmonUrlRequest);
};