void LocationBar::dropEvent(QDropEvent* event) { if (event->mimeData()->hasUrls()) { const QUrl dropUrl = event->mimeData()->urls().at(0); if (WebView::isUrlValid(dropUrl)) { setText(dropUrl.toString()); loadRequest(dropUrl); QFocusEvent event(QFocusEvent::FocusOut); LineEdit::focusOutEvent(&event); return; } } else if (event->mimeData()->hasText()) { const QString dropText = event->mimeData()->text().trimmed(); const QUrl dropUrl = QUrl(dropText); if (WebView::isUrlValid(dropUrl)) { setText(dropUrl.toString()); loadRequest(dropUrl); QFocusEvent event(QFocusEvent::FocusOut); LineEdit::focusOutEvent(&event); return; } else { setText(dropText); setFocus(); return; } } LineEdit::dropEvent(event); }
void QQuickWebEngineViewPrivate::loadFinished(bool success, const QUrl &url, int errorCode, const QString &errorDescription) { Q_Q(QQuickWebEngineView); isLoading = false; m_history->reset(); if (errorCode == WebEngineError::UserAbortedError) { QQuickWebEngineLoadRequest loadRequest(url, QQuickWebEngineView::LoadStoppedStatus); Q_EMIT q->loadingChanged(&loadRequest); return; } if (success) { explicitUrl = QUrl(); QQuickWebEngineLoadRequest loadRequest(url, QQuickWebEngineView::LoadSucceededStatus); Q_EMIT q->loadingChanged(&loadRequest); return; } Q_ASSERT(errorCode); QQuickWebEngineLoadRequest loadRequest( url, QQuickWebEngineView::LoadFailedStatus, errorDescription, errorCode, static_cast<QQuickWebEngineView::ErrorDomain>(WebEngineError::toQtErrorDomain(errorCode))); Q_EMIT q->loadingChanged(&loadRequest); return; }
void DocumentThreadableLoader::makeCrossOriginAccessRequest(const ResourceRequest& request) { ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); ASSERT(m_client); ASSERT(!resource()); // Cross-origin requests are only allowed certain registered schemes. // We would catch this when checking response headers later, but there // is no reason to send a request, preflighted or not, that's guaranteed // to be denied. if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())) { ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, request.url().string(), "Cross origin requests are only supported for protocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); // |this| may be dead here in async mode. return; } // We use isSimpleOrForbiddenRequest() here since |request| may have been // modified in the process of loading (not from the user's input). For // example, referrer. We need to accept them. For security, we must reject // forbidden headers/methods at the point we accept user's input. Not here. if ((m_options.preflightPolicy == ConsiderPreflight && FetchUtils::isSimpleOrForbiddenRequest(request.httpMethod(), request.httpHeaderFields())) || m_options.preflightPolicy == PreventPreflight) { ResourceRequest crossOriginRequest(request); ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); updateRequestForAccessControl(crossOriginRequest, securityOrigin(), effectiveAllowCredentials()); // We update the credentials mode according to effectiveAllowCredentials() here for backward compatibility. But this is not correct. // FIXME: We should set it in the caller of DocumentThreadableLoader. crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() == AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRequest::FetchCredentialsModeOmit); loadRequest(crossOriginRequest, crossOriginOptions); } else { m_crossOriginNonSimpleRequest = true; ResourceRequest crossOriginRequest(request); ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); // Do not set the Origin header for preflight requests. updateRequestForAccessControl(crossOriginRequest, 0, effectiveAllowCredentials()); // We update the credentials mode according to effectiveAllowCredentials() here for backward compatibility. But this is not correct. // FIXME: We should set it in the caller of DocumentThreadableLoader. crossOriginRequest.setFetchCredentialsMode(effectiveAllowCredentials() == AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRequest::FetchCredentialsModeOmit); m_actualRequest = crossOriginRequest; m_actualOptions = crossOriginOptions; bool shouldForcePreflight = InspectorInstrumentation::shouldForceCORSPreflight(m_document); bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSkipPreflight(securityOrigin()->toString(), m_actualRequest.url(), effectiveAllowCredentials(), m_actualRequest.httpMethod(), m_actualRequest.httpHeaderFields()); if (canSkipPreflight && !shouldForcePreflight) { loadActualRequest(); } else { ResourceRequest preflightRequest = createAccessControlPreflightRequest(m_actualRequest, securityOrigin()); // Create a ResourceLoaderOptions for preflight. ResourceLoaderOptions preflightOptions = m_actualOptions; preflightOptions.allowCredentials = DoNotAllowStoredCredentials; loadRequest(preflightRequest, preflightOptions); } } }
void DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request) { ResourceRequest preflightRequest(request.url()); preflightRequest.removeCredentials(); preflightRequest.setHTTPOrigin(m_document->securityOrigin()->toString()); preflightRequest.setAllowCookies(m_options.allowCredentials); preflightRequest.setHTTPMethod("OPTIONS"); preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", request.httpMethod()); const HTTPHeaderMap& requestHeaderFields = request.httpHeaderFields(); if (requestHeaderFields.size() > 0) { Vector<UChar> headerBuffer; HTTPHeaderMap::const_iterator it = requestHeaderFields.begin(); append(headerBuffer, it->first); ++it; HTTPHeaderMap::const_iterator end = requestHeaderFields.end(); for (; it != end; ++it) { headerBuffer.append(','); headerBuffer.append(' '); append(headerBuffer, it->first); } preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", String::adopt(headerBuffer)); } loadRequest(preflightRequest, DoSecurityCheck); }
void LocationCompleter::indexShiftActivated(const QModelIndex &index) { Q_ASSERT(index.isValid()); closePopup(); // Clear locationbar emit clearCompletion(); // Load request if (index.data(LocationCompleterModel::VisitSearchItemRole).toBool()) { loadRequest(LoadRequest(QUrl(m_originalText))); } else { loadRequest(createLoadRequest(index)); } }
void TokenQueueVEG::pollRequests() { std::list<TokenRequestVEG>::iterator it; double pollPeriod = 1.0; // max poll period. for(it = mRequests.begin(); it != mRequests.end();) { if (checkForRequest(it->mToken)) { /* clean it up and handle */ loadRequest(*it); it = mRequests.erase(it); } else { /* calculate desired poll period */ /* if less then current poll period, adjust */ it++; } } if (mRequests.size() > 0) { doPoll(pollPeriod); } }
SessionViewlet::SessionViewlet(QMainWindow *mainWindow, QObject *parent): QObject(parent) { QMenu *sessionMenu = synthclone::getChild<QMenu>(mainWindow, "sessionMenu"); loadAction = synthclone::getChild<QAction>(mainWindow, "loadSessionAction"); connect(loadAction, SIGNAL(triggered()), SIGNAL(loadRequest())); quitAction = synthclone::getChild<QAction>(mainWindow, "quitSessionAction"); connect(quitAction, SIGNAL(triggered()), SIGNAL(quitRequest())); saveAction = synthclone::getChild<QAction>(mainWindow, "saveSessionAction"); connect(saveAction, SIGNAL(triggered()), SIGNAL(saveRequest())); saveAsAction = synthclone::getChild<QAction>(mainWindow, "saveSessionAsAction"); connect(saveAsAction, SIGNAL(triggered()), SIGNAL(saveAsRequest())); // Hack: Optimally, we'd like to give an object name to the separator we // want to retrieve from the QtDesigner file. Unfortunately, QtDesigner // doesn't allow the naming of QAction items that are separators (they all // have to be named 'separator'). So, we have to add the separator here. customItemsSeparator = new QAction(this); customItemsSeparator->setSeparator(true); sessionMenu->insertAction(quitAction, customItemsSeparator); menuViewlet = new MenuViewlet(sessionMenu, customItemsSeparator, this); }
DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options) : m_client(client) , m_document(document) , m_options(options) , m_sameOriginRequest(securityOrigin()->canRequest(request.url())) , m_simpleRequest(true) , m_async(blockingBehavior == LoadAsynchronously) #if ENABLE(INSPECTOR) , m_preflightRequestIdentifier(0) #endif { ASSERT(document); ASSERT(client); // Setting an outgoing referer is only supported in the async code path. ASSERT(m_async || request.httpReferrer().isEmpty()); if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) { loadRequest(request, DoSecurityCheck); return; } if (m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) { m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, request.url().string(), "Cross origin requests are not supported.")); return; } makeCrossOriginAccessRequest(request); }
DocumentThreadableLoader::DocumentThreadableLoader(Document& document, ThreadableLoaderClient& client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options, std::unique_ptr<ContentSecurityPolicy>&& contentSecurityPolicy) : m_client(&client) , m_document(document) , m_options(options) , m_sameOriginRequest(securityOrigin()->canRequest(request.url())) , m_simpleRequest(true) , m_async(blockingBehavior == LoadAsynchronously) , m_contentSecurityPolicy(WTFMove(contentSecurityPolicy)) { // Setting an outgoing referer is only supported in the async code path. ASSERT(m_async || request.httpReferrer().isEmpty()); ASSERT_WITH_SECURITY_IMPLICATION(isAllowedByContentSecurityPolicy(request.url())); if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) { loadRequest(request, DoSecurityCheck); return; } if (m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) { m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, request.url(), "Cross origin requests are not supported.")); return; } makeCrossOriginAccessRequest(request); }
void QQuickWebEngineViewPrivate::adoptWebContents(WebContentsAdapter *webContents) { if (!webContents) { qWarning("Trying to open an empty request, it was either already used or was invalidated." "\nYou must complete the request synchronously within the newViewRequested signal handler." " If a view hasn't been adopted before returning, the request will be invalidated."); return; } Q_Q(QQuickWebEngineView); // This throws away the WebContentsAdapter that has been used until now. // All its states, particularly the loading URL, are replaced by the adopted WebContentsAdapter. adapter = webContents; adapter->initialize(this); // Emit signals for values that might be different from the previous WebContentsAdapter. emit q->titleChanged(); emit q->urlChanged(); emit q->iconChanged(); // FIXME: The current loading state should be stored in the WebContentAdapter // and it should be checked here if the signal emission is really necessary. QQuickWebEngineLoadRequest loadRequest(adapter->activeUrl(), QQuickWebEngineView::LoadSucceededStatus); emit q->loadingChanged(&loadRequest); emit q->loadProgressChanged(); }
void WebView::load(const LoadRequest &request) { const QUrl reqUrl = request.url(); if (reqUrl.isEmpty()) return; if (reqUrl.scheme() == QL1S("javascript")) { const QString scriptSource = reqUrl.toString().mid(11); // Is the javascript source percent encoded or not? // Looking for % character in source should work in most cases if (scriptSource.contains(QL1C('%'))) page()->runJavaScript(QUrl::fromPercentEncoding(scriptSource.toUtf8())); else page()->runJavaScript(scriptSource); return; } if (isUrlValid(reqUrl)) { loadRequest(request); return; } // Make sure to correctly load hosts like localhost (eg. without the dot) if (!reqUrl.isEmpty() && reqUrl.scheme().isEmpty() && !QzTools::containsSpace(reqUrl.path()) && // See #1622 !reqUrl.path().contains(QL1C('.')) ) { QUrl u(QSL("http://") + reqUrl.path()); if (u.isValid()) { // This is blocking... QHostInfo info = QHostInfo::fromName(u.path()); if (info.error() == QHostInfo::NoError) { LoadRequest req = request; req.setUrl(u); loadRequest(req); return; } } } if (qzSettings->searchFromAddressBar) { const LoadRequest searchRequest = mApp->searchEnginesManager()->searchResult(request.urlString()); loadRequest(searchRequest); } }
void DocumentThreadableLoader::preflightSuccess() { OwnPtr<ResourceRequest> actualRequest; actualRequest.swap(m_actualRequest); // It should be ok to skip the security check since we already asked about the preflight request. loadRequest(*actualRequest, SkipSecurityCheck); }
void QQuickWebEngineViewPrivate::loadStarted(const QUrl &provisionalUrl) { Q_Q(QQuickWebEngineView); isLoading = true; m_history->reset(); QQuickWebEngineLoadRequest loadRequest(provisionalUrl, QQuickWebEngineView::LoadStartedStatus); Q_EMIT q->loadingChanged(&loadRequest); }
void DocumentThreadableLoader::preflightSuccess() { OwnPtr<ResourceRequest> actualRequest; actualRequest.swap(m_actualRequest); actualRequest->setHTTPOrigin(securityOrigin()->toAtomicString()); clearResource(); loadRequest(*actualRequest); }
void DocumentThreadableLoader::preflightSuccess() { std::unique_ptr<ResourceRequest> actualRequest; actualRequest.swap(m_actualRequest); actualRequest->setHTTPOrigin(securityOrigin()->toString()); clearResource(); // It should be ok to skip the security check since we already asked about the preflight request. loadRequest(*actualRequest, SkipSecurityCheck); }
void FixtureControlWidget::loadPressed() { QString filename = QFileDialog::getOpenFileName( this, "LOAD: Choose an camera config name", ".", "Text (*.json)" ); if (!filename.isEmpty()) { emit loadRequest(filename); } }
void DocumentThreadableLoader::dispatchInitialRequest(const ResourceRequest& request) { if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) { loadRequest(request, m_resourceLoaderOptions); return; } ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); makeCrossOriginAccessRequest(request); // |this| may be dead here in async mode. }
void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const ResourceRequest& request) { ASSERT(m_options.preflightPolicy != ForcePreflight); ASSERT(m_options.preflightPolicy == PreventPreflight || isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields())); // Cross-origin requests are only allowed for HTTP and registered schemes. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied. if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled(request.url().protocol())) { m_client->didFailAccessControlCheck(ResourceError(errorDomainWebKitInternal, 0, request.url(), "Cross origin requests are only supported for HTTP.")); return; } loadRequest(request, DoSecurityCheck); }
void QtWebPageLoadClient::dispatchLoadFailed(WKErrorRef error) { int errorCode = WKErrorGetErrorCode(error); if (toImpl(error)->platformError().isCancellation() || errorCode == kWKErrorCodeFrameLoadInterruptedByPolicyChange || errorCode == kWKErrorCodePlugInWillHandleLoad) { // Make sure that LoadStartedStatus has a counterpart when e.g. requesting a download. dispatchLoadSucceeded(); return; } QtWebError qtError(error); QWebLoadRequest loadRequest(qtError.url(), QQuickWebView::LoadFailedStatus, qtError.description(), static_cast<QQuickWebView::ErrorDomain>(qtError.type()), qtError.errorCode()); emit m_webView->loadingChanged(&loadRequest); }
void DocumentThreadableLoader::loadActualRequest() { ResourceRequest actualRequest = m_actualRequest; ResourceLoaderOptions actualOptions = m_actualOptions; m_actualRequest = ResourceRequest(); m_actualOptions = ResourceLoaderOptions(); actualRequest.setHTTPOrigin(securityOrigin()); clearResource(); loadRequest(actualRequest, actualOptions); }
void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const ResourceRequest& request) { ASSERT(isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields())); // Cross-origin requests are only defined for HTTP. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied. // FIXME: Consider allowing simple CORS requests to non-HTTP URLs. if (!request.url().protocolInHTTPFamily()) { m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, request.url().string(), "Cross origin requests are only supported for HTTP.")); return; } loadRequest(request, DoSecurityCheck); }
void DocumentThreadableLoader::dispatchInitialRequest( const ResourceRequest& request) { if (!request.isExternalRequest() && (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests)) { loadRequest(request, m_resourceLoaderOptions); return; } DCHECK(m_options.crossOriginRequestPolicy == UseAccessControl || request.isExternalRequest()); makeCrossOriginAccessRequest(request); }
void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const ResourceRequest& request) { ASSERT(isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields())); // Cross-origin requests are only defined for HTTP. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied. if (!request.url().protocolInHTTPFamily()) { m_client->didFail(ResourceError()); return; } // Make a copy of the passed request so that we can modify some details. ResourceRequest crossOriginRequest(request); crossOriginRequest.setHTTPOrigin(m_document->securityOrigin()->toString()); loadRequest(crossOriginRequest, DoSecurityCheck); }
void DocumentThreadableLoader::loadActualRequest() { ResourceRequest actualRequest = m_actualRequest; ResourceLoaderOptions actualOptions = m_actualOptions; m_actualRequest = ResourceRequest(); m_actualOptions = ResourceLoaderOptions(); clearResource(); // Explicitly set the SkipServiceWorker flag here. Even if the page was not // controlled by a SW when the preflight request was sent, a new SW may be // controlling the page now by calling clients.claim(). We should not send // the actual request to the SW. https://crbug.com/604583 actualRequest.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); prepareCrossOriginRequest(actualRequest); loadRequest(actualRequest, actualOptions); }
void TokenQueue::pollRequests() { double pollPeriod = 0.1; // max poll period. if (mRequests.empty()) { return; } TokenRequest req; req = mRequests.front(); mRequests.pop_front(); if (checkForRequest(req.mToken)) { /* clean it up and handle */ loadRequest(req); } else { // checkForRequest returns also true when the request cannot be found (e.g. removed by a timeout) //#define MAX_REQUEST_AGE 30 // /* drop old requests too */ // if (time(NULL) - req.mRequestTs.tv_sec < MAX_REQUEST_AGE) // { mRequests.push_back(req); // } // else // { // std::cerr << "TokenQueue::loadRequest(): "; // std::cerr << "Dropping old Token: " << req.mToken << " Type: " << req.mType; // std::cerr << std::endl; // } } if (mRequests.size() > 0) { doPoll(pollPeriod); } }
DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options) : m_client(client) , m_document(document) , m_options(options) , m_sameOriginRequest(securityOrigin()->canRequest(request.url())) , m_async(blockingBehavior == LoadAsynchronously) #if ENABLE(INSPECTOR) , m_preflightRequestIdentifier(0) #endif { ASSERT(document); ASSERT(client); // Setting an outgoing referer is only supported in the async code path. ASSERT(m_async || request.httpReferrer().isEmpty()); if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) { loadRequest(request, DoSecurityCheck); return; } if (m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) { m_client->didFail(ResourceError(errorDomainWebKitInternal, 0, request.url().string(), "Cross origin requests are not supported.")); return; } ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); OwnPtr<ResourceRequest> crossOriginRequest = adoptPtr(new ResourceRequest(request)); updateRequestForAccessControl(*crossOriginRequest, securityOrigin(), m_options.allowCredentials); if ((m_options.preflightPolicy == ConsiderPreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields())) || m_options.preflightPolicy == PreventPreflight) makeSimpleCrossOriginAccessRequest(*crossOriginRequest); else { m_actualRequest = crossOriginRequest.release(); if (CrossOriginPreflightResultCache::shared().canSkipPreflight(securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields())) preflightSuccess(); else makeCrossOriginAccessRequestWithPreflight(*m_actualRequest); } }
DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options) : m_client(client) , m_document(document) , m_options(options) #if PLATFORM(APOLLO) , m_sameOriginRequest(document->securityOrigin()->canRequestExt(request.url(), document)) #else , m_sameOriginRequest(document->securityOrigin()->canRequest(request.url())) #endif , m_async(blockingBehavior == LoadAsynchronously) { ASSERT(document); ASSERT(client); if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) { loadRequest(request, DoSecurityCheck); return; } if (m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) { m_client->didFail(ResourceError()); return; } ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl); OwnPtr<ResourceRequest> crossOriginRequest(new ResourceRequest(request)); crossOriginRequest->removeCredentials(); crossOriginRequest->setAllowCookies(m_options.allowCredentials); if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(crossOriginRequest->httpMethod(), crossOriginRequest->httpHeaderFields())) makeSimpleCrossOriginAccessRequest(*crossOriginRequest); else { m_actualRequest.set(crossOriginRequest.release()); if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), m_actualRequest->url(), m_options.allowCredentials, m_actualRequest->httpMethod(), m_actualRequest->httpHeaderFields())) preflightSuccess(); else makeCrossOriginAccessRequestWithPreflight(*m_actualRequest); } }
void LocationCompleter::indexActivated(const QModelIndex &index) { Q_ASSERT(index.isValid()); closePopup(); // Clear locationbar emit clearCompletion(); bool ok; const int tabPos = index.data(LocationCompleterModel::TabPositionTabRole).toInt(&ok); // Switch to tab with simple index activation if (ok && tabPos > -1) { BrowserWindow* window = static_cast<BrowserWindow*>(index.data(LocationCompleterModel::TabPositionWindowRole).value<void*>()); Q_ASSERT(window); switchToTab(window, tabPos); return; } loadRequest(createLoadRequest(index)); }
void DocumentThreadableLoader::makeCrossOriginAccessRequest( const ResourceRequest& request) { DCHECK(m_options.crossOriginRequestPolicy == UseAccessControl || request.isExternalRequest()); DCHECK(m_client); DCHECK(!resource()); // Cross-origin requests are only allowed certain registered schemes. We would // catch this when checking response headers later, but there is no reason to // send a request, preflighted or not, that's guaranteed to be denied. if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled( request.url().protocol())) { InspectorInstrumentation:: documentThreadableLoaderFailedToStartLoadingForClient(m_document, m_client); ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(ResourceError( errorDomainBlinkInternal, 0, request.url().getString(), "Cross origin requests are only supported for protocol schemes: " + SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); return; } // Non-secure origins may not make "external requests": // https://mikewest.github.io/cors-rfc1918/#integration-fetch if (!document().isSecureContext() && request.isExternalRequest()) { ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck( ResourceError(errorDomainBlinkInternal, 0, request.url().getString(), "Requests to internal network resources are not allowed " "from non-secure contexts (see https://goo.gl/Y0ZkNV). " "This is an experimental restriction which is part of " "'https://mikewest.github.io/cors-rfc1918/'.")); return; } ResourceRequest crossOriginRequest(request); ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); crossOriginRequest.removeCredentials(); crossOriginRequest.setAllowStoredCredentials(effectiveAllowCredentials() == AllowStoredCredentials); // We update the credentials mode according to effectiveAllowCredentials() // here for backward compatibility. But this is not correct. // FIXME: We should set it in the caller of DocumentThreadableLoader. crossOriginRequest.setFetchCredentialsMode( effectiveAllowCredentials() == AllowStoredCredentials ? WebURLRequest::FetchCredentialsModeInclude : WebURLRequest::FetchCredentialsModeOmit); // We use isSimpleOrForbiddenRequest() here since |request| may have been // modified in the process of loading (not from the user's input). For // example, referrer. We need to accept them. For security, we must reject // forbidden headers/methods at the point we accept user's input. Not here. if (!request.isExternalRequest() && ((m_options.preflightPolicy == ConsiderPreflight && FetchUtils::isSimpleOrForbiddenRequest(request.httpMethod(), request.httpHeaderFields())) || m_options.preflightPolicy == PreventPreflight)) { prepareCrossOriginRequest(crossOriginRequest); loadRequest(crossOriginRequest, crossOriginOptions); } else { bool shouldForcePreflight = request.isExternalRequest() || InspectorInstrumentation::shouldForceCORSPreflight(m_document); bool canSkipPreflight = CrossOriginPreflightResultCache::shared().canSkipPreflight( getSecurityOrigin()->toString(), crossOriginRequest.url(), effectiveAllowCredentials(), crossOriginRequest.httpMethod(), crossOriginRequest.httpHeaderFields()); if (canSkipPreflight && !shouldForcePreflight) { if (getSecurityOrigin()) crossOriginRequest.setHTTPOrigin(getSecurityOrigin()); if (m_overrideReferrer) crossOriginRequest.setHTTPReferrer(m_referrerAfterRedirect); prepareCrossOriginRequest(crossOriginRequest); loadRequest(crossOriginRequest, crossOriginOptions); } else { ResourceRequest preflightRequest = createAccessControlPreflightRequest( crossOriginRequest, getSecurityOrigin()); // Create a ResourceLoaderOptions for preflight. ResourceLoaderOptions preflightOptions = crossOriginOptions; preflightOptions.allowCredentials = DoNotAllowStoredCredentials; m_actualRequest = crossOriginRequest; m_actualOptions = crossOriginOptions; prepareCrossOriginRequest(crossOriginRequest); loadRequest(preflightRequest, preflightOptions); } } }
void DocumentThreadableLoader::start(const ResourceRequest& request) { // Setting an outgoing referer is only supported in the async code path. DCHECK(m_async || request.httpReferrer().isEmpty()); m_sameOriginRequest = getSecurityOrigin()->canRequestNoSuborigin(request.url()); m_requestContext = request.requestContext(); m_redirectMode = request.fetchRedirectMode(); if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) { InspectorInstrumentation:: documentThreadableLoaderFailedToStartLoadingForClient(m_document, m_client); ThreadableLoaderClient* client = m_client; clear(); client->didFail(ResourceError(errorDomainBlinkInternal, 0, request.url().getString(), "Cross origin requests are not supported.")); return; } m_requestStartedSeconds = monotonicallyIncreasingTime(); // Save any headers on the request here. If this request redirects // cross-origin, we cancel the old request create a new one, and copy these // headers. m_requestHeaders = request.httpHeaderFields(); // DocumentThreadableLoader is used by all javascript initiated fetch, so we // use this chance to record non-GET fetch script requests. However, this is // based on the following assumptions, so please be careful when adding // similar logic: // - ThreadableLoader is used as backend for all javascript initiated network // fetches. // - Note that ThreadableLoader is also used for non-network fetch such as // FileReaderLoader. However it emulates GET method so signal is not // recorded here. // - ThreadableLoader w/ non-GET request is only created from javascript // initiated fetch. // - Some non-script initiated fetches such as WorkerScriptLoader also use // ThreadableLoader, but they are guaranteed to use GET method. if (request.httpMethod() != HTTPNames::GET) { if (Page* page = m_document->page()) page->chromeClient().didObserveNonGetFetchFromScript(); } ResourceRequest newRequest(request); if (m_requestContext != WebURLRequest::RequestContextFetch) { // When the request context is not "fetch", |crossOriginRequestPolicy| // represents the fetch request mode, and |credentialsRequested| represents // the fetch credentials mode. So we set those flags here so that we can see // the correct request mode and credentials mode in the service worker's // fetch event handler. switch (m_options.crossOriginRequestPolicy) { case DenyCrossOriginRequests: newRequest.setFetchRequestMode( WebURLRequest::FetchRequestModeSameOrigin); break; case UseAccessControl: if (m_options.preflightPolicy == ForcePreflight) { newRequest.setFetchRequestMode( WebURLRequest::FetchRequestModeCORSWithForcedPreflight); } else { newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeCORS); } break; case AllowCrossOriginRequests: SECURITY_CHECK(IsNoCORSAllowedContext(m_requestContext, request.skipServiceWorker())); newRequest.setFetchRequestMode(WebURLRequest::FetchRequestModeNoCORS); break; } if (m_resourceLoaderOptions.allowCredentials == AllowStoredCredentials) { newRequest.setFetchCredentialsMode( WebURLRequest::FetchCredentialsModeInclude); } else { newRequest.setFetchCredentialsMode( WebURLRequest::FetchCredentialsModeSameOrigin); } } // We assume that ServiceWorker is skipped for sync requests and unsupported // protocol requests by content/ code. if (m_async && request.skipServiceWorker() == WebURLRequest::SkipServiceWorker::None && SchemeRegistry::shouldTreatURLSchemeAsAllowingServiceWorkers( request.url().protocol()) && m_document->fetcher()->isControlledByServiceWorker()) { if (newRequest.fetchRequestMode() == WebURLRequest::FetchRequestModeCORS || newRequest.fetchRequestMode() == WebURLRequest::FetchRequestModeCORSWithForcedPreflight) { m_fallbackRequestForServiceWorker = ResourceRequest(request); // m_fallbackRequestForServiceWorker is used when a regular controlling // service worker doesn't handle a cross origin request. When this happens // we still want to give foreign fetch a chance to handle the request, so // only skip the controlling service worker for the fallback request. This // is currently safe because of http://crbug.com/604084 the // wasFallbackRequiredByServiceWorker flag is never set when foreign fetch // handled a request. m_fallbackRequestForServiceWorker.setSkipServiceWorker( WebURLRequest::SkipServiceWorker::Controlling); } loadRequest(newRequest, m_resourceLoaderOptions); return; } dispatchInitialRequest(newRequest); }