diff --git a/atom/browser/net/atom_network_delegate.cc b/atom/browser/net/atom_network_delegate.cc index 6bc25027db1f..f12911f286e3 100644 --- a/atom/browser/net/atom_network_delegate.cc +++ b/atom/browser/net/atom_network_delegate.cc @@ -190,6 +190,10 @@ template void OnListenerResultInIO(const net::CompletionCallback& callback, T out, scoped_ptr response) { + // The request has been destroyed. + if (callback.is_null()) + return; + ReadFromResponseObject(*response.get(), out); bool cancel = false; @@ -312,10 +316,7 @@ void AtomNetworkDelegate::OnCompleted(net::URLRequest* request, bool started) { if (request->status().status() == net::URLRequestStatus::FAILED || request->status().status() == net::URLRequestStatus::CANCELED) { // Error event. - if (ContainsKey(simple_listeners_, kOnErrorOccurred)) - OnErrorOccurred(request); - else - brightray::NetworkDelegate::OnCompleted(request, started); + OnErrorOccurred(request, started); return; } else if (request->response_headers() && net::HttpResponseHeaders::IsRedirectResponseCode( @@ -334,7 +335,17 @@ void AtomNetworkDelegate::OnCompleted(net::URLRequest* request, bool started) { request->was_cached()); } -void AtomNetworkDelegate::OnErrorOccurred(net::URLRequest* request) { +void AtomNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) { + callbacks_.erase(request->identifier()); +} + +void AtomNetworkDelegate::OnErrorOccurred( + net::URLRequest* request, bool started) { + if (!ContainsKey(simple_listeners_, kOnErrorOccurred)) { + brightray::NetworkDelegate::OnCompleted(request, started); + return; + } + HandleSimpleEvent(kOnErrorOccurred, request, request->was_cached(), request->status()); } @@ -353,8 +364,12 @@ int AtomNetworkDelegate::HandleResponseEvent( scoped_ptr details(new base::DictionaryValue); FillDetailsObject(details.get(), request, args...); + // The |request| could be destroyed before the |callback| is called. + callbacks_[request->identifier()].Reset(callback); + const auto& cancelable = callbacks_[request->identifier()].callback(); + ResponseCallback response = - base::Bind(OnListenerResultInUI, callback, out); + base::Bind(OnListenerResultInUI, cancelable, out); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::Bind(RunResponseListener, info.listener, base::Passed(&details), diff --git a/atom/browser/net/atom_network_delegate.h b/atom/browser/net/atom_network_delegate.h index 8950a1b5110c..579f33f6d7ad 100644 --- a/atom/browser/net/atom_network_delegate.h +++ b/atom/browser/net/atom_network_delegate.h @@ -9,7 +9,7 @@ #include #include "brightray/browser/network_delegate.h" -#include "base/callback.h" +#include "base/cancelable_callback.h" #include "base/values.h" #include "extensions/common/url_pattern.h" #include "net/base/net_errors.h" @@ -85,10 +85,11 @@ class AtomNetworkDelegate : public brightray::NetworkDelegate { const GURL& new_location) override; void OnResponseStarted(net::URLRequest* request) override; void OnCompleted(net::URLRequest* request, bool started) override; - - void OnErrorOccurred(net::URLRequest* request); + void OnURLRequestDestroyed(net::URLRequest* request) override; private: + void OnErrorOccurred(net::URLRequest* request, bool started); + template void HandleSimpleEvent(SimpleEvent type, net::URLRequest* request, @@ -101,7 +102,8 @@ class AtomNetworkDelegate : public brightray::NetworkDelegate { Args... args); std::map simple_listeners_; - std::map response_listeners_;; + std::map response_listeners_; + std::map> callbacks_; DISALLOW_COPY_AND_ASSIGN(AtomNetworkDelegate); };