diff options
author | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-13 09:01:28 +0000 |
---|---|---|
committer | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-13 09:01:28 +0000 |
commit | 34b6db5e3093d11b88a925001a0230f81bf844f9 (patch) | |
tree | 8c1891417e7a5178b36ed367141737a307c647a2 /net | |
parent | 462232c4cf79e1b51d9a2f721c26f812172ad640 (diff) | |
download | chromium_src-34b6db5e3093d11b88a925001a0230f81bf844f9.zip chromium_src-34b6db5e3093d11b88a925001a0230f81bf844f9.tar.gz chromium_src-34b6db5e3093d11b88a925001a0230f81bf844f9.tar.bz2 |
Revert 92331 - Fix leaking request IDs in webRequest API
The current webRequest API did not guarantee that either onCompleted or onErrorOccurred is called for each request. If an extension fills a REQUEST_ID -> URL hashmap for all requests at the onBeforeRequest event, and tried to delete the entries on onCompleted and onErrorOccurred, some entries remained in the hashmap.
BUG=86139
TEST=execute example extension attached to bug
Review URL: http://codereview.chromium.org/7190007
TBR=battre@chromium.org
Review URL: http://codereview.chromium.org/7351011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@92339 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/url_request/url_request.cc | 92 | ||||
-rw-r--r-- | net/url_request/url_request.h | 40 | ||||
-rw-r--r-- | net/url_request/url_request_http_job.cc | 22 | ||||
-rw-r--r-- | net/url_request/url_request_job.cc | 67 | ||||
-rw-r--r-- | net/url_request/url_request_job.h | 14 | ||||
-rw-r--r-- | net/url_request/url_request_test_util.cc | 4 | ||||
-rw-r--r-- | net/url_request/url_request_test_util.h | 2 | ||||
-rw-r--r-- | net/url_request/url_request_unittest.cc | 21 |
8 files changed, 53 insertions, 209 deletions
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index 40e1be6..7b55201 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc @@ -124,8 +124,7 @@ URLRequest::URLRequest(const GURL& url, Delegate* delegate) priority_(LOWEST), identifier_(GenerateURLRequestIdentifier()), ALLOW_THIS_IN_INITIALIZER_LIST( - before_request_callback_(this, &URLRequest::BeforeRequestComplete)), - has_notified_completion_(false) { + before_request_callback_(this, &URLRequest::BeforeRequestComplete)) { SIMPLE_STATS_COUNTER("URLRequestCount"); // Sanity check out environment. @@ -136,11 +135,11 @@ URLRequest::URLRequest(const GURL& url, Delegate* delegate) } URLRequest::~URLRequest() { - Cancel(); - if (context_ && context_->network_delegate()) context_->network_delegate()->NotifyURLRequestDestroyed(this); + Cancel(); + if (job_) OrphanJob(); @@ -370,10 +369,6 @@ GURL URLRequest::GetSanitizedReferrer() const { return ret; } -void URLRequest::set_delegate(Delegate* delegate) { - delegate_ = delegate; -} - void URLRequest::Start() { response_info_.request_time = Time::Now(); @@ -484,11 +479,6 @@ void URLRequest::DoCancel(int os_error, const SSLInfo& ssl_info) { job_->Kill(); - // We need to notify about the end of this job here synchronously. The - // Job sends an asynchronous notification but by the time this is processed, - // our |context_| is NULL. - NotifyRequestCompleted(); - // The Job will call our NotifyDone method asynchronously. This is done so // that the Delegate implementation can call Cancel without having to worry // about being called recursively. @@ -514,8 +504,6 @@ bool URLRequest::Read(IOBuffer* dest, int dest_size, int* bytes_read) { bool rv = job_->Read(dest, dest_size, bytes_read); // If rv is false, the status cannot be success. DCHECK(rv || status_.status() != URLRequestStatus::SUCCESS); - if (rv && *bytes_read <= 0 && status_.is_success()) - NotifyRequestCompleted(); return rv; } @@ -524,8 +512,7 @@ void URLRequest::StopCaching() { job_->StopCaching(); } -void URLRequest::NotifyReceivedRedirect(const GURL& location, - bool* defer_redirect) { +void URLRequest::ReceivedRedirect(const GURL& location, bool* defer_redirect) { URLRequestJob* job = URLRequestJobManager::GetInstance()->MaybeInterceptRedirect(this, location); @@ -536,7 +523,7 @@ void URLRequest::NotifyReceivedRedirect(const GURL& location, } } -void URLRequest::NotifyResponseStarted() { +void URLRequest::ResponseStarted() { scoped_refptr<NetLog::EventParameters> params; if (!status_.is_success()) params = new NetLogIntegerParameter("net_error", status_.os_error()); @@ -547,22 +534,10 @@ void URLRequest::NotifyResponseStarted() { if (job) { RestartWithJob(job); } else { - if (delegate_) { - // In some cases (e.g. an event was canceled), we might have sent the - // completion event and receive a NotifyResponseStarted() later. - if (!has_notified_completion_ && status_.is_success()) { - if (context_ && context_->network_delegate()) - context_->network_delegate()->NotifyResponseStarted(this); - } - - // Notify in case the entire URL Request has been finished. - if (!has_notified_completion_ && !status_.is_success()) - NotifyRequestCompleted(); - + if (context_ && context_->network_delegate()) + context_->network_delegate()->NotifyResponseStarted(this); + if (delegate_) delegate_->OnResponseStarted(this); - // Nothing may appear below this line as OnResponseStarted may delete - // |this|. - } } } @@ -722,55 +697,4 @@ void URLRequest::SetUserData(const void* key, UserData* data) { user_data_[key] = linked_ptr<UserData>(data); } -void URLRequest::NotifyAuthRequired(AuthChallengeInfo* auth_info) { - if (delegate_) - delegate_->OnAuthRequired(this, auth_info); -} - -void URLRequest::NotifyCertificateRequested( - SSLCertRequestInfo* cert_request_info) { - if (delegate_) - delegate_->OnCertificateRequested(this, cert_request_info); -} - -void URLRequest::NotifySSLCertificateError(int cert_error, - X509Certificate* cert) { - if (delegate_) - delegate_->OnSSLCertificateError(this, cert_error, cert); -} - -bool URLRequest::CanGetCookies() { - if (delegate_) - return delegate_->CanGetCookies(this); - return false; -} - -bool URLRequest::CanSetCookie(const std::string& cookie_line, - CookieOptions* options) { - if (delegate_) - return delegate_->CanSetCookie(this, cookie_line, options); - return false; -} - - -void URLRequest::NotifyReadCompleted(int bytes_read) { - if (delegate_) - delegate_->OnReadCompleted(this, bytes_read); - - // Notify in case the entire URL Request has been finished. - if (bytes_read <= 0) - NotifyRequestCompleted(); -} - -void URLRequest::NotifyRequestCompleted() { - // TODO(battre): Get rid of this check, according to willchan it should - // not be needed. - if (has_notified_completion_) - return; - - has_notified_completion_ = true; - if (context_ && context_->network_delegate()) - context_->network_delegate()->NotifyCompleted(this); -} - } // namespace net diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index cbd7bab..bf1cb84 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h @@ -306,9 +306,10 @@ class NET_API URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe) { // Returns the referrer header with potential username and password removed. GURL GetSanitizedReferrer() const; - // Sets the delegate of the request. This value may be changed at any time, + // The delegate of the request. This value may be changed at any time, // and it is permissible for it to be null. - void set_delegate(Delegate* delegate); + Delegate* delegate() const { return delegate_; } + void set_delegate(Delegate* delegate) { delegate_ = delegate; } // The data comprising the request message body is specified as a sequence of // data segments and/or files containing data to upload. These methods may @@ -576,7 +577,11 @@ class NET_API URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe) { int Redirect(const GURL& location, int http_status_code); // Called by URLRequestJob to allow interception when a redirect occurs. - void NotifyReceivedRedirect(const GURL& location, bool* defer_redirect); + void ReceivedRedirect(const GURL& location, bool* defer_redirect); + + // Called by URLRequestJob to allow interception when the final response + // occurs. + void ResponseStarted(); // Allow an interceptor's URLRequestJob to restart this request. // Should only be called if the original job has not started a response. @@ -584,7 +589,6 @@ class NET_API URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe) { private: friend class URLRequestJob; - typedef std::map<const void*, linked_ptr<UserData> > UserDataMap; // Resumes or blocks a request paused by the NetworkDelegate::OnBeforeRequest @@ -610,27 +614,6 @@ class NET_API URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe) { // passed values. void DoCancel(int os_error, const SSLInfo& ssl_info); - // Notifies the network delegate that the request has been completed. - // This does not imply a successful completion. Also a canceled request is - // considered completed. - void NotifyRequestCompleted(); - - // Called by URLRequestJob to allow interception when the final response - // occurs. - void NotifyResponseStarted(); - - bool has_delegate() const { return delegate_ != NULL; } - - // These functions delegate to |delegate_| and may only be used if - // |delegate_| is not NULL. See URLRequest::Delegate for the meaning - // of these functions. - void NotifyAuthRequired(AuthChallengeInfo* auth_info); - void NotifyCertificateRequested(SSLCertRequestInfo* cert_request_info); - void NotifySSLCertificateError(int cert_error, X509Certificate* cert); - bool CanGetCookies(); - bool CanSetCookie(const std::string& cookie_line, CookieOptions* options); - void NotifyReadCompleted(int bytes_read); - // Contextual information used for this request (can be NULL). This contains // most of the dependencies which are shared between requests (disk cache, // cookie store, socket pool, etc.) @@ -650,8 +633,6 @@ class NET_API URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe) { int load_flags_; // Flags indicating the request type for the load; // expected values are LOAD_* enums above. - // Never access methods of the |delegate_| directly. Always use the - // Notify... methods for this. Delegate* delegate_; // Current error status of the job. When no error has been encountered, this @@ -691,11 +672,6 @@ class NET_API URLRequest : NON_EXPORTED_BASE(public base::NonThreadSafe) { // is ready to be resumed or canceled. CompletionCallbackImpl<URLRequest> before_request_callback_; - // Safe-guard to ensure that we do not send multiple "I am completed" - // messages to network delegate. - // TODO(battre): Remove this. http://crbug.com/89049 - bool has_notified_completion_; - DISALLOW_COPY_AND_ASSIGN(URLRequest); }; diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index c3f354c..d36de09 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc @@ -504,8 +504,9 @@ void URLRequestHttpJob::AddCookieHeaderAndStart() { return; bool allow = true; - if ((request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES) || - !CanGetCookies()) { + if (request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES || + (request_->delegate() && + !request_->delegate()->CanGetCookies(request_))) { allow = false; } @@ -561,11 +562,12 @@ void URLRequestHttpJob::SaveNextCookie() { CookieOptions options; if (!(request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) && - request_->context()->cookie_store()) { + request_->delegate() && request_->context()->cookie_store()) { CookieOptions options; options.set_include_httponly(); - if (CanSetCookie( - response_cookies_[response_cookies_save_index_], &options)) { + if (request_->delegate()->CanSetCookie( + request_, + response_cookies_[response_cookies_save_index_], &options)) { request_->context()->cookie_store()->SetCookieWithOptions( request_->url(), response_cookies_[response_cookies_save_index_], options); @@ -686,7 +688,7 @@ void URLRequestHttpJob::OnStartCompleted(int result) { RecordTimer(); // If the request was destroyed, then there is no more work to do. - if (!request_) + if (!request_ || !request_->delegate()) return; // If the transaction was destroyed, then the job was cancelled, and @@ -729,11 +731,11 @@ void URLRequestHttpJob::OnStartCompleted(int result) { // what we should do. // TODO(wtc): also pass ssl_info.cert_status, or just pass the whole // ssl_info. - NotifySSLCertificateError( - result, transaction_->GetResponseInfo()->ssl_info.cert); + request_->delegate()->OnSSLCertificateError( + request_, result, transaction_->GetResponseInfo()->ssl_info.cert); } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { - NotifyCertificateRequested( - transaction_->GetResponseInfo()->cert_request_info); + request_->delegate()->OnCertificateRequested( + request_, transaction_->GetResponseInfo()->cert_request_info); } else { NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result)); } diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc index cd02911..b664c6c 100644 --- a/net/url_request/url_request_job.cc +++ b/net/url_request/url_request_job.cc @@ -44,7 +44,6 @@ void URLRequestJob::SetExtraRequestHeaders(const HttpRequestHeaders& headers) { } void URLRequestJob::Kill() { - method_factory_.RevokeAll(); // Make sure the request is notified that we are done. We assume that the // request took care of setting its error status before calling Kill. if (request_) @@ -214,39 +213,8 @@ URLRequestJob::~URLRequestJob() { base::SystemMonitor::Get()->RemoveObserver(this); } -void URLRequestJob::NotifyCertificateRequested( - SSLCertRequestInfo* cert_request_info) { - if (!request_) - return; // The request was destroyed, so there is no more work to do. - - request_->NotifyCertificateRequested(cert_request_info); -} - -void URLRequestJob::NotifySSLCertificateError(int cert_error, - X509Certificate* cert) { - if (!request_) - return; // The request was destroyed, so there is no more work to do. - - request_->NotifySSLCertificateError(cert_error, cert); -} - -bool URLRequestJob::CanGetCookies() { - if (!request_) - return false; // The request was destroyed, so there is no more work to do. - - return request_->CanGetCookies(); -} - -bool URLRequestJob::CanSetCookie(const std::string& cookie_line, - CookieOptions* options) { - if (!request_) - return false; // The request was destroyed, so there is no more work to do. - - return request_->CanSetCookie(cookie_line, options); -} - void URLRequestJob::NotifyHeadersComplete() { - if (!request_ || !request_->has_delegate()) + if (!request_ || !request_->delegate()) return; // The request was destroyed, so there is no more work to do. if (has_handled_response_) @@ -284,11 +252,10 @@ void URLRequestJob::NotifyHeadersComplete() { } bool defer_redirect = false; - request_->NotifyReceivedRedirect(new_location, &defer_redirect); + request_->ReceivedRedirect(new_location, &defer_redirect); - // Ensure that the request wasn't detached or destroyed in - // NotifyReceivedRedirect - if (!request_ || !request_->has_delegate()) + // Ensure that the request wasn't detached or destroyed in ReceivedRedirect + if (!request_ || !request_->delegate()) return; // If we were not cancelled, then maybe follow the redirect. @@ -307,7 +274,7 @@ void URLRequestJob::NotifyHeadersComplete() { // Need to check for a NULL auth_info because the server may have failed // to send a challenge with the 401 response. if (auth_info) { - request_->NotifyAuthRequired(auth_info); + request_->delegate()->OnAuthRequired(request_, auth_info); // Wait for SetAuth or CancelAuth to be called. return; } @@ -324,11 +291,11 @@ void URLRequestJob::NotifyHeadersComplete() { base::StringToInt64(content_length, &expected_content_size_); } - request_->NotifyResponseStarted(); + request_->ResponseStarted(); } void URLRequestJob::NotifyReadComplete(int bytes_read) { - if (!request_ || !request_->has_delegate()) + if (!request_ || !request_->delegate()) return; // The request was destroyed, so there is no more work to do. // TODO(darin): Bug 1004233. Re-enable this test once all of the chrome @@ -358,10 +325,10 @@ void URLRequestJob::NotifyReadComplete(int bytes_read) { // Filter the data. int filter_bytes_read = 0; if (ReadFilteredData(&filter_bytes_read)) { - request_->NotifyReadCompleted(filter_bytes_read); + request_->delegate()->OnReadCompleted(request_, filter_bytes_read); } } else { - request_->NotifyReadCompleted(bytes_read); + request_->delegate()->OnReadCompleted(request_, bytes_read); } DVLOG(1) << __FUNCTION__ << "() " << "\"" << (request_ ? request_->url().spec() : "???") << "\"" @@ -375,7 +342,7 @@ void URLRequestJob::NotifyStartError(const URLRequestStatus &status) { has_handled_response_ = true; if (request_) { request_->set_status(status); - request_->NotifyResponseStarted(); + request_->ResponseStarted(); } } @@ -403,6 +370,11 @@ void URLRequestJob::NotifyDone(const URLRequestStatus &status) { request_->set_status(status); } + if (request_ && request_->context() && + request_->context()->network_delegate()) { + request_->context()->network_delegate()->NotifyCompleted(request_); + } + // Complete this notification later. This prevents us from re-entering the // delegate if we're done because of a synchronous call. MessageLoop::current()->PostTask( @@ -414,22 +386,23 @@ void URLRequestJob::CompleteNotifyDone() { // Check if we should notify the delegate that we're done because of an error. if (request_ && !request_->status().is_success() && - request_->has_delegate()) { + request_->delegate()) { // We report the error differently depending on whether we've called // OnResponseStarted yet. if (has_handled_response_) { // We signal the error by calling OnReadComplete with a bytes_read of -1. - request_->NotifyReadCompleted(-1); + request_->delegate()->OnReadCompleted(request_, -1); } else { has_handled_response_ = true; - request_->NotifyResponseStarted(); + request_->ResponseStarted(); } } } void URLRequestJob::NotifyCanceled() { if (!done_) { - NotifyDone(URLRequestStatus(URLRequestStatus::CANCELED, ERR_ABORTED)); + NotifyDone(URLRequestStatus(URLRequestStatus::CANCELED, + ERR_ABORTED)); } } diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h index e9887ad..d2261ca 100644 --- a/net/url_request/url_request_job.h +++ b/net/url_request/url_request_job.h @@ -24,11 +24,9 @@ namespace net { class AuthChallengeInfo; -class CookieOptions; class HttpRequestHeaders; class HttpResponseInfo; class IOBuffer; -class SSLCertRequestInfo; class URLRequest; class UploadData; class URLRequestStatus; @@ -192,18 +190,6 @@ class NET_API URLRequestJob : public base::RefCounted<URLRequestJob>, friend class base::RefCounted<URLRequestJob>; virtual ~URLRequestJob(); - // Notifies the job that a certificate is requested. - void NotifyCertificateRequested(SSLCertRequestInfo* cert_request_info); - - // Notifies the job about an SSL certificate error. - void NotifySSLCertificateError(int cert_error, X509Certificate* cert); - - // Delegates to URLRequest::Delegate. - bool CanGetCookies(); - - // Delegates to URLRequest::Delegate. - bool CanSetCookie(const std::string& cookie_line, CookieOptions* options); - // Notifies the job that headers have been received. void NotifyHeadersComplete(); diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc index 716e1e7..0bfe9447 100644 --- a/net/url_request/url_request_test_util.cc +++ b/net/url_request/url_request_test_util.cc @@ -244,8 +244,7 @@ TestNetworkDelegate::TestNetworkDelegate() : last_os_error_(0), error_count_(0), created_requests_(0), - destroyed_requests_(0), - completed_requests_(0) { + destroyed_requests_(0) { } TestNetworkDelegate::~TestNetworkDelegate() {} @@ -287,7 +286,6 @@ void TestNetworkDelegate::OnRawBytesRead(const net::URLRequest& request, } void TestNetworkDelegate::OnCompleted(net::URLRequest* request) { - completed_requests_++; if (request->status().status() == net::URLRequestStatus::FAILED) { error_count_++; last_os_error_ = request->status().os_error(); diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h index 74d8fab..f7755b8 100644 --- a/net/url_request/url_request_test_util.h +++ b/net/url_request/url_request_test_util.h @@ -179,7 +179,6 @@ class TestNetworkDelegate : public net::NetworkDelegate { int error_count() const { return error_count_; } int created_requests() const { return created_requests_; } int destroyed_requests() const { return destroyed_requests_; } - int completed_requests() const { return completed_requests_; } protected: // net::NetworkDelegate: @@ -207,7 +206,6 @@ class TestNetworkDelegate : public net::NetworkDelegate { int error_count_; int created_requests_; int destroyed_requests_; - int completed_requests_; }; #endif // NET_URL_REQUEST_URL_REQUEST_TEST_UTIL_H_ diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 281daaf..6e51ff6 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc @@ -298,7 +298,8 @@ TEST_F(URLRequestTestHTTP, NetworkDelegateTunnelConnectionFailed) { EXPECT_EQ(0, d.received_redirect_count()); EXPECT_EQ(1, network_delegate.error_count()); - EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, network_delegate.last_os_error()); + EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, + network_delegate.last_os_error()); } } @@ -2458,7 +2459,8 @@ TEST_F(URLRequestTest, NetworkDelegateProxyError) { TestURLRequest req(GURL("http://example.com"), &d); req.set_method("GET"); - scoped_ptr<MockHostResolverBase> host_resolver(new MockHostResolver); + scoped_ptr<MockHostResolverBase> host_resolver( + new MockHostResolver); host_resolver->rules()->AddSimulatedFailure("*"); scoped_refptr<TestURLRequestContext> context( new TestURLRequestContext("myproxy:70", host_resolver.release())); @@ -2475,7 +2477,6 @@ TEST_F(URLRequestTest, NetworkDelegateProxyError) { EXPECT_EQ(1, network_delegate.error_count()); EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, network_delegate.last_os_error()); - EXPECT_EQ(1, network_delegate.completed_requests()); } // Check that it is impossible to change the referrer in the extra headers of @@ -2523,20 +2524,6 @@ TEST_F(URLRequestTest, DoNotOverrideReferrer) { } } -// Make sure that net::NetworkDelegate::NotifyCompleted is called if -// content is empty. -TEST_F(URLRequestTest, RequestCompletionForEmptyResponse) { - TestNetworkDelegate network_delegate; - TestDelegate d; - TestURLRequest req(GURL("data:,"), &d); - req.set_context(new TestURLRequestContext()); - req.context()->set_network_delegate(&network_delegate); - req.Start(); - MessageLoop::current()->Run(); - EXPECT_EQ("", d.data_received()); - EXPECT_EQ(1, network_delegate.completed_requests()); -} - class URLRequestTestFTP : public URLRequestTest { public: URLRequestTestFTP() : test_server_(TestServer::TYPE_FTP, FilePath()) { |