blob: 9a84d2c09d30c8d610915be990fbe7eea879b146 [file] [log] [blame]
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
#include "net/base/net_errors.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
namespace blink {
namespace {
constexpr char kThrottledErrorDescription[] =
"Request throttled. Visit http://dev.chromium.org/throttling for more "
"information.";
} // namespace
int ResourceError::BlockedByXSSAuditorErrorCode() {
return net::ERR_BLOCKED_BY_XSS_AUDITOR;
}
ResourceError ResourceError::CancelledError(const KURL& url) {
return ResourceError(net::ERR_ABORTED, url, base::nullopt);
}
ResourceError ResourceError::CancelledDueToAccessCheckError(
const KURL& url,
ResourceRequestBlockedReason blocked_reason) {
ResourceError error = CancelledError(url);
error.is_access_check_ = true;
error.should_collapse_initiator_ =
blocked_reason == ResourceRequestBlockedReason::kSubresourceFilter;
return error;
}
ResourceError ResourceError::CancelledDueToAccessCheckError(
const KURL& url,
ResourceRequestBlockedReason blocked_reason,
const String& localized_description) {
ResourceError error = CancelledDueToAccessCheckError(url, blocked_reason);
error.localized_description_ = localized_description;
return error;
}
ResourceError ResourceError::CacheMissError(const KURL& url) {
return ResourceError(net::ERR_CACHE_MISS, url, base::nullopt);
}
ResourceError ResourceError::TimeoutError(const KURL& url) {
return ResourceError(net::ERR_TIMED_OUT, url, base::nullopt);
}
ResourceError ResourceError::Failure(const KURL& url) {
return ResourceError(net::ERR_FAILED, url, base::nullopt);
}
ResourceError::ResourceError(
int error_code,
const KURL& url,
base::Optional<network::CORSErrorStatus> cors_error_status)
: error_code_(error_code),
failing_url_(url),
cors_error_status_(cors_error_status) {
DCHECK_NE(error_code_, 0);
InitializeDescription();
}
ResourceError::ResourceError(const WebURLError& error)
: error_code_(error.reason()),
extended_error_code_(error.extended_reason()),
failing_url_(error.url()),
is_access_check_(error.is_web_security_violation()),
has_copy_in_cache_(error.has_copy_in_cache()),
cors_error_status_(error.cors_error_status()) {
DCHECK_NE(error_code_, 0);
InitializeDescription();
}
ResourceError ResourceError::Copy() const {
ResourceError error_copy(error_code_, failing_url_.Copy(),
cors_error_status_);
error_copy.extended_error_code_ = extended_error_code_;
error_copy.has_copy_in_cache_ = has_copy_in_cache_;
error_copy.localized_description_ = localized_description_.IsolatedCopy();
error_copy.is_access_check_ = is_access_check_;
return error_copy;
}
ResourceError::operator WebURLError() const {
WebURLError::HasCopyInCache has_copy_in_cache =
has_copy_in_cache_ ? WebURLError::HasCopyInCache::kTrue
: WebURLError::HasCopyInCache::kFalse;
if (cors_error_status_) {
DCHECK_EQ(net::ERR_FAILED, error_code_);
return WebURLError(*cors_error_status_, has_copy_in_cache, failing_url_);
}
return WebURLError(error_code_, extended_error_code_, has_copy_in_cache,
is_access_check_
? WebURLError::IsWebSecurityViolation::kTrue
: WebURLError::IsWebSecurityViolation::kFalse,
failing_url_);
}
bool ResourceError::Compare(const ResourceError& a, const ResourceError& b) {
if (a.ErrorCode() != b.ErrorCode())
return false;
if (a.FailingURL() != b.FailingURL())
return false;
if (a.LocalizedDescription() != b.LocalizedDescription())
return false;
if (a.IsAccessCheck() != b.IsAccessCheck())
return false;
if (a.HasCopyInCache() != b.HasCopyInCache())
return false;
if (a.CORSErrorStatus() != b.CORSErrorStatus())
return false;
if (a.extended_error_code_ != b.extended_error_code_)
return false;
return true;
}
bool ResourceError::IsTimeout() const {
return error_code_ == net::ERR_TIMED_OUT;
}
bool ResourceError::IsCancellation() const {
return error_code_ == net::ERR_ABORTED;
}
bool ResourceError::IsCacheMiss() const {
return error_code_ == net::ERR_CACHE_MISS;
}
bool ResourceError::WasBlockedByResponse() const {
return error_code_ == net::ERR_BLOCKED_BY_RESPONSE;
}
base::Optional<ResourceRequestBlockedReason>
ResourceError::GetResourceRequestBlockedReason() const {
if (error_code_ != net::ERR_BLOCKED_BY_CLIENT &&
error_code_ != net::ERR_BLOCKED_BY_RESPONSE) {
return base::nullopt;
}
return static_cast<ResourceRequestBlockedReason>(extended_error_code_);
}
namespace {
String DescriptionForBlockedByClientOrResponse(int error, int extended_error) {
if (extended_error == 0)
return WebString::FromASCII(net::ErrorToString(error));
std::string detail;
switch (static_cast<ResourceRequestBlockedReason>(extended_error)) {
case ResourceRequestBlockedReason::kOther:
NOTREACHED(); // extended_error == 0, handled above
break;
case ResourceRequestBlockedReason::kCSP:
detail = "CSP";
break;
case ResourceRequestBlockedReason::kMixedContent:
detail = "MixedContent";
break;
case ResourceRequestBlockedReason::kOrigin:
detail = "Origin";
break;
case ResourceRequestBlockedReason::kInspector:
detail = "Inspector";
break;
case ResourceRequestBlockedReason::kSubresourceFilter:
detail = "SubresourceFilter";
break;
case ResourceRequestBlockedReason::kContentType:
detail = "ContentType";
break;
}
return WebString::FromASCII(net::ErrorToString(error) + "." + detail);
}
} // namespace
void ResourceError::InitializeDescription() {
if (error_code_ == net::ERR_TEMPORARILY_THROTTLED) {
localized_description_ = WebString::FromASCII(kThrottledErrorDescription);
} else if (error_code_ == net::ERR_BLOCKED_BY_CLIENT ||
error_code_ == net::ERR_BLOCKED_BY_RESPONSE) {
localized_description_ = DescriptionForBlockedByClientOrResponse(
error_code_, extended_error_code_);
} else {
localized_description_ = WebString::FromASCII(
net::ExtendedErrorToString(error_code_, extended_error_code_));
}
}
std::ostream& operator<<(std::ostream& os, const ResourceError& error) {
return os << ", ErrorCode = " << error.ErrorCode()
<< ", FailingURL = " << error.FailingURL()
<< ", LocalizedDescription = " << error.LocalizedDescription()
<< ", IsCancellation = " << error.IsCancellation()
<< ", IsAccessCheck = " << error.IsAccessCheck()
<< ", IsTimeout = " << error.IsTimeout()
<< ", HasCopyInCache = " << error.HasCopyInCache()
<< ", IsCacheMiss = " << error.IsCacheMiss();
}
} // namespace blink