Пример #1
0
void NetworkResourceLoader::retrieveCacheEntry(const ResourceRequest& request)
{
    ASSERT(canUseCache(request));

    RefPtr<NetworkResourceLoader> loader(this);
    NetworkCache::singleton().retrieve(request, { m_parameters.webPageID, m_parameters.webFrameID }, [loader, request](auto entry) {
        if (loader->hasOneRef()) {
            // The loader has been aborted and is only held alive by this lambda.
            return;
        }
        if (!entry) {
            loader->startNetworkLoad(request);
            return;
        }
        if (entry->redirectRequest()) {
            loader->dispatchWillSendRequestForCacheEntry(WTFMove(entry));
            return;
        }
        if (loader->m_parameters.needsCertificateInfo && !entry->response().certificateInfo()) {
            loader->startNetworkLoad(request);
            return;
        }
        if (entry->needsValidation() || request.cachePolicy() == WebCore::RefreshAnyCacheData) {
            loader->validateCacheEntry(WTFMove(entry));
            return;
        }
        loader->didRetrieveCacheEntry(WTFMove(entry));
    });
}
Пример #2
0
void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
{
    // Note that there are no asserts here as there are for the other callbacks. This is due to the
    // fact that this "callback" is sent when starting every load, and the state of callback
    // deferrals plays less of a part in this function in preventing the bad behavior deferring 
    // callbacks is meant to prevent.
    ASSERT(!newRequest.isNull());
    
    // The additional processing can do anything including possibly removing the last
    // reference to this object; one example of this is 3266216.
    RefPtr<MainResourceLoader> protect(this);
    
    // Update cookie policy base URL as URL changes, except for subframes, which use the
    // URL of the main frame which doesn't change when we redirect.
    if (frameLoader()->isLoadingMainFrame())
        newRequest.setMainDocumentURL(newRequest.url());
    
    // If we're fielding a redirect in response to a POST, force a load from origin, since
    // this is a common site technique to return to a page viewing some data that the POST
    // just modified.
    // Also, POST requests always load from origin, but this does not affect subresources.
    if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse))
        newRequest.setCachePolicy(ReloadIgnoringCacheData);

    if (!newRequest.isNull()) {
        ResourceLoader::willSendRequest(newRequest, redirectResponse);
        setRequest(newRequest);
    }
    
    // Don't set this on the first request. It is set when the main load was started.
    frameLoader()->setRequest(newRequest);
    
    ref(); // balanced by deref in continueAfterNavigationPolicy
    frameLoader()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this);
}
void ResourceRequestBase::setAsIsolatedCopy(const ResourceRequest& other)
{
    setURL(other.url().isolatedCopy());
    setCachePolicy(other.cachePolicy());
    setTimeoutInterval(other.timeoutInterval());
    setFirstPartyForCookies(other.firstPartyForCookies().isolatedCopy());
    setHTTPMethod(other.httpMethod().isolatedCopy());
    setPriority(other.priority());
    setRequester(other.requester());

    updateResourceRequest();
    m_httpHeaderFields = other.httpHeaderFields().isolatedCopy();

    size_t encodingCount = other.m_responseContentDispositionEncodingFallbackArray.size();
    if (encodingCount > 0) {
        String encoding1 = other.m_responseContentDispositionEncodingFallbackArray[0].isolatedCopy();
        String encoding2;
        String encoding3;
        if (encodingCount > 1) {
            encoding2 = other.m_responseContentDispositionEncodingFallbackArray[1].isolatedCopy();
            if (encodingCount > 2)
                encoding3 = other.m_responseContentDispositionEncodingFallbackArray[2].isolatedCopy();
        }
        ASSERT(encodingCount <= 3);
        setResponseContentDispositionEncodingFallbackArray(encoding1, encoding2, encoding3);
    }
    if (other.m_httpBody)
        setHTTPBody(other.m_httpBody->isolatedCopy());
    setAllowCookies(other.m_allowCookies);

    const_cast<ResourceRequest&>(asResourceRequest()).doPlatformSetAsIsolatedCopy(other);
}
Пример #4
0
void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
{
    // Note that there are no asserts here as there are for the other callbacks. This is due to the
    // fact that this "callback" is sent when starting every load, and the state of callback
    // deferrals plays less of a part in this function in preventing the bad behavior deferring 
    // callbacks is meant to prevent.
    ASSERT(!newRequest.isNull());

    if (!frameLoader()->checkIfFormActionAllowedByCSP(newRequest.url())) {
        cancelMainResourceLoad(frameLoader()->cancelledError(newRequest));
        return;
    }

    ASSERT(timing()->fetchStart());
    if (!redirectResponse.isNull()) {
        // If the redirecting url is not allowed to display content from the target origin,
        // then block the redirect.
        RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
        if (!redirectingOrigin->canDisplay(newRequest.url())) {
            FrameLoader::reportLocalLoadFailed(m_frame, newRequest.url().string());
            cancelMainResourceLoad(frameLoader()->cancelledError(newRequest));
            return;
        }
        timing()->addRedirect(redirectResponse.url(), newRequest.url());
    }

    // Update cookie policy base URL as URL changes, except for subframes, which use the
    // URL of the main frame which doesn't change when we redirect.
    if (frameLoader()->isLoadingMainFrame())
        newRequest.setFirstPartyForCookies(newRequest.url());

    // If we're fielding a redirect in response to a POST, force a load from origin, since
    // this is a common site technique to return to a page viewing some data that the POST
    // just modified.
    // Also, POST requests always load from origin, but this does not affect subresources.
    if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse))
        newRequest.setCachePolicy(ReloadIgnoringCacheData);

    Frame* top = m_frame->tree()->top();
    if (top) {
        if (!top->loader()->mixedContentChecker()->canDisplayInsecureContent(top->document()->securityOrigin(), newRequest.url())) {
            cancelMainResourceLoad(frameLoader()->cancelledError(newRequest));
            return;
        }
    }

    setRequest(newRequest);

    if (redirectResponse.isNull())
        return;

    frameLoader()->client()->dispatchDidReceiveServerRedirectForProvisionalLoad();
    if (!shouldContinueForNavigationPolicy(newRequest))
        stopLoadingForPolicyChange();
}
Пример #5
0
bool equalIgnoringHeaderFields(const ResourceRequest& a, const ResourceRequest& b)
{
    if (a.url() != b.url())
        return false;

    if (a.cachePolicy() != b.cachePolicy())
        return false;

    if (a.timeoutInterval() != b.timeoutInterval())
        return false;

    if (a.firstPartyForCookies() != b.firstPartyForCookies())
        return false;

    if (a.httpMethod() != b.httpMethod())
        return false;

    if (a.allowStoredCredentials() != b.allowStoredCredentials())
        return false;

    if (a.priority() != b.priority())
        return false;

    if (a.referrerPolicy() != b.referrerPolicy())
        return false;

    FormData* formDataA = a.httpBody();
    FormData* formDataB = b.httpBody();

    if (!formDataA)
        return !formDataB;
    if (!formDataB)
        return !formDataA;

    if (*formDataA != *formDataB)
        return false;

    return true;
}
Пример #6
0
void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
{
    // Note that there are no asserts here as there are for the other callbacks. This is due to the
    // fact that this "callback" is sent when starting every load, and the state of callback
    // deferrals plays less of a part in this function in preventing the bad behavior deferring
    // callbacks is meant to prevent.
    ASSERT(!newRequest.isNull());
    if (isFormSubmission(m_triggeringAction.type()) && !m_frame->document()->contentSecurityPolicy()->allowFormAction(newRequest.url())) {
        cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
        return;
    }

    ASSERT(timing()->fetchStart());
    if (!redirectResponse.isNull()) {
        // If the redirecting url is not allowed to display content from the target origin,
        // then block the redirect.
        RefPtr<SecurityOrigin> redirectingOrigin = SecurityOrigin::create(redirectResponse.url());
        if (!redirectingOrigin->canDisplay(newRequest.url())) {
            FrameLoader::reportLocalLoadFailed(m_frame, newRequest.url().string());
            cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
            return;
        }
        timing()->addRedirect(redirectResponse.url(), newRequest.url());
    }

    // If we're fielding a redirect in response to a POST, force a load from origin, since
    // this is a common site technique to return to a page viewing some data that the POST
    // just modified.
    if (newRequest.cachePolicy() == UseProtocolCachePolicy && isRedirectAfterPost(newRequest, redirectResponse))
        newRequest.setCachePolicy(ReloadBypassingCache);

    // If this is a sub-frame, check for mixed content blocking against the top frame.
    if (m_frame->tree().parent()) {
        // FIXME: This does not yet work with out-of-process iframes.
        Frame* top = m_frame->tree().top();
        if (top->isLocalFrame() && !toLocalFrame(top)->loader().mixedContentChecker()->canRunInsecureContent(toLocalFrame(top)->document()->securityOrigin(), newRequest.url())) {
            cancelMainResourceLoad(ResourceError::cancelledError(newRequest.url()));
            return;
        }
    }

    m_request = newRequest;

    if (redirectResponse.isNull())
        return;

    appendRedirect(newRequest.url());
    frameLoader()->client()->dispatchDidReceiveServerRedirectForProvisionalLoad();
    if (!shouldContinueForNavigationPolicy(newRequest))
        cancelMainResourceLoad(ResourceError::cancelledError(m_request.url()));
}
Пример #7
0
void ResourceFetcher::addAdditionalRequestHeaders(ResourceRequest& request, Resource::Type type)
{
    if (!frame())
        return;

    if (request.cachePolicy() == UseProtocolCachePolicy)
        request.setCachePolicy(resourceRequestCachePolicy(request, type));
    if (request.requestContext() == WebURLRequest::RequestContextUnspecified)
        determineRequestContext(request, type);
    if (type == Resource::LinkPrefetch || type == Resource::LinkSubresource)
        request.setHTTPHeaderField("Purpose", "prefetch");

    context().addAdditionalRequestHeaders(document(), request, (type == Resource::MainResource) ? FetchMainResource : FetchSubresource);
}
Пример #8
0
static inline NetworkRequest::CachePolicy platformCachePolicyForRequest(const ResourceRequest& request)
{
    switch (request.cachePolicy()) {
    case WebCore::UseProtocolCachePolicy:
        return NetworkRequest::UseProtocolCachePolicy;
    case WebCore::ReloadIgnoringCacheData:
        return NetworkRequest::ReloadIgnoringCacheData;
    case WebCore::ReturnCacheDataElseLoad:
        return NetworkRequest::ReturnCacheDataElseLoad;
    case WebCore::ReturnCacheDataDontLoad:
        return NetworkRequest::ReturnCacheDataDontLoad;
    default:
        return NetworkRequest::UseProtocolCachePolicy;
    }
}
Пример #9
0
void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
{
    // Note that there are no asserts here as there are for the other callbacks. This is due to the
    // fact that this "callback" is sent when starting every load, and the state of callback
    // deferrals plays less of a part in this function in preventing the bad behavior deferring 
    // callbacks is meant to prevent.
    ASSERT(!newRequest.isNull());
    
    // The additional processing can do anything including possibly removing the last
    // reference to this object; one example of this is 3266216.
    RefPtr<MainResourceLoader> protect(this);
    
    // Update cookie policy base URL as URL changes, except for subframes, which use the
    // URL of the main frame which doesn't change when we redirect.
    if (frameLoader()->isLoadingMainFrame())
        newRequest.setFirstPartyForCookies(newRequest.url());
    
    // If we're fielding a redirect in response to a POST, force a load from origin, since
    // this is a common site technique to return to a page viewing some data that the POST
    // just modified.
    // Also, POST requests always load from origin, but this does not affect subresources.
    if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse))
        newRequest.setCachePolicy(ReloadIgnoringCacheData);

    ResourceLoader::willSendRequest(newRequest, redirectResponse);
    
    // Don't set this on the first request. It is set when the main load was started.
    m_documentLoader->setRequest(newRequest);

    Frame* top = m_frame->tree()->top();
    if (top != m_frame)
        frameLoader()->checkIfDisplayInsecureContent(top->document()->securityOrigin(), newRequest.url());

    // FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate
    // listener. But there's no way to do that in practice. So instead we cancel later if the
    // listener tells us to. In practice that means the navigation policy needs to be decided
    // synchronously for these redirect cases.
    if (!redirectResponse.isNull()) {
        ref(); // balanced by deref in continueAfterNavigationPolicy
        frameLoader()->policyChecker()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this);
    }
}
void ArgumentCoder<ResourceRequest>::encodePlatformData(ArgumentEncoder& encoder, const ResourceRequest& resourceRequest)
{
    encoder << resourceRequest.url().string();
    encoder << resourceRequest.httpMethod();
    encoder << resourceRequest.httpHeaderFields();
    encoder << resourceRequest.timeoutInterval();

    // FIXME: Do not encode HTTP message body.
    // 1. It can be large and thus costly to send across.
    // 2. It is misleading to provide a body with some requests, while others use body streams, which cannot be serialized at all.
    FormData* httpBody = resourceRequest.httpBody();
    encoder << static_cast<bool>(httpBody);
    if (httpBody)
        encoder << httpBody->flattenToString();

    encoder << resourceRequest.firstPartyForCookies().string();
    encoder << resourceRequest.allowCookies();
    encoder.encodeEnum(resourceRequest.priority());
    encoder.encodeEnum(resourceRequest.cachePolicy());
    encoder.encodeEnum(resourceRequest.requester());

    encoder << static_cast<uint32_t>(resourceRequest.soupMessageFlags());
    encoder << resourceRequest.initiatingPageID();
}
Пример #11
0
CFURLRequestRef cfURLRequest(const ResourceRequest& request)
{
    CFURLRef url = request.url().createCFURL();
    CFURLRef mainDocumentURL = request.mainDocumentURL().createCFURL();

    CFMutableURLRequestRef cfRequest = CFURLRequestCreateMutable(0, url, (CFURLRequestCachePolicy)request.cachePolicy(), request.timeoutInterval(), mainDocumentURL);

    CFRelease(url);
    CFRelease(mainDocumentURL);

    CFStringRef requestMethod = request.httpMethod().createCFString();
    CFURLRequestSetHTTPRequestMethod(cfRequest, requestMethod);
    CFRelease(requestMethod);

    addHeadersFromHashMap(cfRequest, request.httpHeaderFields());
    setHTTPBody(cfRequest, request.httpBody());
    CFURLRequestSetShouldHandleHTTPCookies(cfRequest, request.allowHTTPCookies());

    return cfRequest;
}
Пример #12
0
void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
{
    // Note that there are no asserts here as there are for the other callbacks. This is due to the
    // fact that this "callback" is sent when starting every load, and the state of callback
    // deferrals plays less of a part in this function in preventing the bad behavior deferring 
    // callbacks is meant to prevent.
    ASSERT(!newRequest.isNull());

    // The additional processing can do anything including possibly removing the last
    // reference to this object; one example of this is 3266216.
    RefPtr<MainResourceLoader> protect(this);

    ASSERT(documentLoader()->timing()->fetchStart);
    if (!redirectResponse.isNull()) {
        DocumentLoadTiming* documentLoadTiming = documentLoader()->timing();

        // Check if the redirected url is allowed to access the redirecting url's timing information.
        RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(newRequest.url());
        if (!securityOrigin->canRequest(redirectResponse.url()))
            documentLoadTiming->hasCrossOriginRedirect = true;

        documentLoadTiming->redirectCount++;
        if (!documentLoadTiming->redirectStart)
            documentLoadTiming->redirectStart = documentLoadTiming->fetchStart;
        documentLoadTiming->redirectEnd = currentTime();
        documentLoadTiming->fetchStart = documentLoadTiming->redirectEnd;
    }

    // Update cookie policy base URL as URL changes, except for subframes, which use the
    // URL of the main frame which doesn't change when we redirect.
    if (frameLoader()->isLoadingMainFrame())
        newRequest.setFirstPartyForCookies(newRequest.url());

    // If we're fielding a redirect in response to a POST, force a load from origin, since
    // this is a common site technique to return to a page viewing some data that the POST
    // just modified.
    // Also, POST requests always load from origin, but this does not affect subresources.
    if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse))
        newRequest.setCachePolicy(ReloadIgnoringCacheData);

    Frame* top = m_frame->tree()->top();
    if (top != m_frame) {
        if (!frameLoader()->checkIfDisplayInsecureContent(top->document()->securityOrigin(), newRequest.url())) {
            cancel();
            return;
        }
    }

    ResourceLoader::willSendRequest(newRequest, redirectResponse);

    // Don't set this on the first request. It is set when the main load was started.
    m_documentLoader->setRequest(newRequest);

#if ENABLE(OFFLINE_WEB_APPLICATIONS)
    if (!redirectResponse.isNull()) {
        // We checked application cache for initial URL, now we need to check it for redirected one.
        ASSERT(!m_substituteData.isValid());
        documentLoader()->applicationCacheHost()->maybeLoadMainResourceForRedirect(newRequest, m_substituteData);
    }
#endif

    // FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate
    // listener. But there's no way to do that in practice. So instead we cancel later if the
    // listener tells us to. In practice that means the navigation policy needs to be decided
    // synchronously for these redirect cases.
    if (!redirectResponse.isNull()) {
        ref(); // balanced by deref in continueAfterNavigationPolicy
        frameLoader()->policyChecker()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this);
    }
}
TEST(ResourceRequestTest, CrossThreadResourceRequestData)
{
    ResourceRequest original;
    original.setURL(KURL(ParsedURLString, "http://www.example.com/test.htm"));
    original.setCachePolicy(UseProtocolCachePolicy);
    original.setTimeoutInterval(10);
    original.setFirstPartyForCookies(KURL(ParsedURLString, "http://www.example.com/first_party.htm"));
    original.setHTTPMethod(AtomicString("GET", AtomicString::ConstructFromLiteral));
    original.setHTTPHeaderField(AtomicString("Foo"), AtomicString("Bar"));
    original.setHTTPHeaderField(AtomicString("Piyo"), AtomicString("Fuga"));
    original.setPriority(ResourceLoadPriorityLow, 20);

    RefPtr<FormData> originalBody(FormData::create("Test Body"));
    original.setHTTPBody(originalBody);
    original.setAllowStoredCredentials(false);
    original.setReportUploadProgress(false);
    original.setHasUserGesture(false);
    original.setDownloadToFile(false);
    original.setSkipServiceWorker(false);
    original.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS);
    original.setFetchCredentialsMode(WebURLRequest::FetchCredentialsModeSameOrigin);
    original.setRequestorID(30);
    original.setRequestorProcessID(40);
    original.setAppCacheHostID(50);
    original.setRequestContext(WebURLRequest::RequestContextAudio);
    original.setFrameType(WebURLRequest::FrameTypeNested);
    original.setHTTPReferrer(Referrer("http://www.example.com/referrer.htm", ReferrerPolicyDefault));

    EXPECT_STREQ("http://www.example.com/test.htm", original.url().string().utf8().data());
    EXPECT_EQ(UseProtocolCachePolicy, original.cachePolicy());
    EXPECT_EQ(10, original.timeoutInterval());
    EXPECT_STREQ("http://www.example.com/first_party.htm", original.firstPartyForCookies().string().utf8().data());
    EXPECT_STREQ("GET", original.httpMethod().utf8().data());
    EXPECT_STREQ("Bar", original.httpHeaderFields().get("Foo").utf8().data());
    EXPECT_STREQ("Fuga", original.httpHeaderFields().get("Piyo").utf8().data());
    EXPECT_EQ(ResourceLoadPriorityLow, original.priority());
    EXPECT_STREQ("Test Body", original.httpBody()->flattenToString().utf8().data());
    EXPECT_FALSE(original.allowStoredCredentials());
    EXPECT_FALSE(original.reportUploadProgress());
    EXPECT_FALSE(original.hasUserGesture());
    EXPECT_FALSE(original.downloadToFile());
    EXPECT_FALSE(original.skipServiceWorker());
    EXPECT_EQ(WebURLRequest::FetchRequestModeCORS, original.fetchRequestMode());
    EXPECT_EQ(WebURLRequest::FetchCredentialsModeSameOrigin, original.fetchCredentialsMode());
    EXPECT_EQ(30, original.requestorID());
    EXPECT_EQ(40, original.requestorProcessID());
    EXPECT_EQ(50, original.appCacheHostID());
    EXPECT_EQ(WebURLRequest::RequestContextAudio, original.requestContext());
    EXPECT_EQ(WebURLRequest::FrameTypeNested, original.frameType());
    EXPECT_STREQ("http://www.example.com/referrer.htm", original.httpReferrer().utf8().data());
    EXPECT_EQ(ReferrerPolicyDefault, original.referrerPolicy());

    OwnPtr<CrossThreadResourceRequestData> data1(original.copyData());
    OwnPtr<ResourceRequest> copy1(ResourceRequest::adopt(data1.release()));

    EXPECT_STREQ("http://www.example.com/test.htm", copy1->url().string().utf8().data());
    EXPECT_EQ(UseProtocolCachePolicy, copy1->cachePolicy());
    EXPECT_EQ(10, copy1->timeoutInterval());
    EXPECT_STREQ("http://www.example.com/first_party.htm", copy1->firstPartyForCookies().string().utf8().data());
    EXPECT_STREQ("GET", copy1->httpMethod().utf8().data());
    EXPECT_STREQ("Bar", copy1->httpHeaderFields().get("Foo").utf8().data());
    EXPECT_EQ(ResourceLoadPriorityLow, copy1->priority());
    EXPECT_STREQ("Test Body", copy1->httpBody()->flattenToString().utf8().data());
    EXPECT_FALSE(copy1->allowStoredCredentials());
    EXPECT_FALSE(copy1->reportUploadProgress());
    EXPECT_FALSE(copy1->hasUserGesture());
    EXPECT_FALSE(copy1->downloadToFile());
    EXPECT_FALSE(copy1->skipServiceWorker());
    EXPECT_EQ(WebURLRequest::FetchRequestModeCORS, copy1->fetchRequestMode());
    EXPECT_EQ(WebURLRequest::FetchCredentialsModeSameOrigin, copy1->fetchCredentialsMode());
    EXPECT_EQ(30, copy1->requestorID());
    EXPECT_EQ(40, copy1->requestorProcessID());
    EXPECT_EQ(50, copy1->appCacheHostID());
    EXPECT_EQ(WebURLRequest::RequestContextAudio, copy1->requestContext());
    EXPECT_EQ(WebURLRequest::FrameTypeNested, copy1->frameType());
    EXPECT_STREQ("http://www.example.com/referrer.htm", copy1->httpReferrer().utf8().data());
    EXPECT_EQ(ReferrerPolicyDefault, copy1->referrerPolicy());

    copy1->setAllowStoredCredentials(true);
    copy1->setReportUploadProgress(true);
    copy1->setHasUserGesture(true);
    copy1->setDownloadToFile(true);
    copy1->setSkipServiceWorker(true);
    copy1->setFetchRequestMode(WebURLRequest::FetchRequestModeNoCORS);
    copy1->setFetchCredentialsMode(WebURLRequest::FetchCredentialsModeInclude);

    OwnPtr<CrossThreadResourceRequestData> data2(copy1->copyData());
    OwnPtr<ResourceRequest> copy2(ResourceRequest::adopt(data2.release()));
    EXPECT_TRUE(copy2->allowStoredCredentials());
    EXPECT_TRUE(copy2->reportUploadProgress());
    EXPECT_TRUE(copy2->hasUserGesture());
    EXPECT_TRUE(copy2->downloadToFile());
    EXPECT_TRUE(copy2->skipServiceWorker());
    EXPECT_EQ(WebURLRequest::FetchRequestModeNoCORS, copy1->fetchRequestMode());
    EXPECT_EQ(WebURLRequest::FetchCredentialsModeInclude, copy1->fetchCredentialsMode());
}