void DocumentThreadableLoader::handlePreflightResponse(const ResourceResponse& response) { String accessControlErrorDescription; if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescription, m_requestContext)) { handlePreflightFailure(response.url().string(), "Response to preflight request doesn't pass access control check: " + accessControlErrorDescription); // |this| may be dead here in async mode. return; } if (!passesPreflightStatusCheck(response, accessControlErrorDescription)) { handlePreflightFailure(response.url().string(), accessControlErrorDescription); // |this| may be dead here in async mode. return; } OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult = adoptPtr(new CrossOriginPreflightResultCacheItem(effectiveAllowCredentials())); if (!preflightResult->parse(response, accessControlErrorDescription) || !preflightResult->allowsCrossOriginMethod(m_actualRequest.httpMethod(), accessControlErrorDescription) || !preflightResult->allowsCrossOriginHeaders(m_actualRequest.httpHeaderFields(), accessControlErrorDescription)) { handlePreflightFailure(response.url().string(), accessControlErrorDescription); // |this| may be dead here in async mode. return; } CrossOriginPreflightResultCache::shared().appendEntry(securityOrigin()->toString(), m_actualRequest.url(), preflightResult.release()); }
AbstractDatabase::AbstractDatabase(ScriptExecutionContext* context, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize) : m_scriptExecutionContext(context) , m_name(name.crossThreadString()) , m_expectedVersion(expectedVersion.crossThreadString()) , m_displayName(displayName.crossThreadString()) , m_estimatedSize(estimatedSize) , m_guid(0) , m_opened(false) , m_new(false) { ASSERT(context->isContextThread()); m_contextThreadSecurityOrigin = m_scriptExecutionContext->securityOrigin(); m_databaseAuthorizer = DatabaseAuthorizer::create(infoTableName); if (m_name.isNull()) m_name = ""; { MutexLocker locker(guidMutex()); m_guid = guidForOriginAndName(securityOrigin()->toString(), name); HashSet<AbstractDatabase*>* hashSet = guidToDatabaseMap().get(m_guid); if (!hashSet) { hashSet = new HashSet<AbstractDatabase*>; guidToDatabaseMap().set(m_guid, hashSet); } hashSet->add(this); } m_filename = DatabaseTracker::tracker().fullPathForDatabase(securityOrigin(), m_name); DatabaseTracker::tracker().addOpenDatabase(this); }
DatabaseBackendBase::DatabaseBackendBase(PassRefPtr<DatabaseBackendContext> databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, DatabaseType databaseType) : m_databaseContext(databaseContext) , m_name(name.isolatedCopy()) , m_expectedVersion(expectedVersion.isolatedCopy()) , m_displayName(displayName.isolatedCopy()) , m_estimatedSize(estimatedSize) , m_guid(0) , m_opened(false) , m_new(false) , m_isSyncDatabase(databaseType == DatabaseType::Sync) { m_contextThreadSecurityOrigin = m_databaseContext->securityOrigin()->isolatedCopy(); m_databaseAuthorizer = DatabaseAuthorizer::create(infoTableName); if (m_name.isNull()) m_name = ""; { MutexLocker locker(guidMutex()); m_guid = guidForOriginAndName(securityOrigin()->toString(), name); HashSet<DatabaseBackendBase*>* hashSet = guidToDatabaseMap().get(m_guid); if (!hashSet) { hashSet = new HashSet<DatabaseBackendBase*>; guidToDatabaseMap().set(m_guid, hashSet); } hashSet->add(this); } m_filename = DatabaseManager::manager().fullPathForDatabase(securityOrigin(), m_name); }
DatabaseBackendBase::DatabaseBackendBase(PassRefPtr<DatabaseBackendContext> databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize, DatabaseType databaseType) : m_databaseContext(databaseContext) , m_name(name.isolatedCopy()) , m_expectedVersion(expectedVersion.isolatedCopy()) , m_displayName(displayName.isolatedCopy()) , m_estimatedSize(estimatedSize) , m_opened(false) , m_new(false) , m_isSyncDatabase(databaseType == DatabaseType::Sync) { m_contextThreadSecurityOrigin = m_databaseContext->securityOrigin()->isolatedCopy(); m_databaseAuthorizer = DatabaseAuthorizer::create(infoTableName); if (m_name.isNull()) m_name = emptyString(); { std::lock_guard<std::mutex> locker(guidMutex()); m_guid = guidForOriginAndName(securityOrigin()->toString(), name); std::unique_ptr<HashSet<DatabaseBackendBase*>>& hashSet = guidToDatabaseMap().add(m_guid, nullptr).iterator->value; if (!hashSet) hashSet = std::make_unique<HashSet<DatabaseBackendBase*>>(); hashSet->add(this); } m_filename = DatabaseManager::manager().fullPathForDatabase(securityOrigin(), m_name); }
void DocumentThreadableLoader::handleResponse(unsigned long identifier, const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) { ASSERT(m_client); if (!m_actualRequest.isNull()) { reportResponseReceived(identifier, response); handlePreflightResponse(response); // |this| may be dead here in async mode. return; } if (response.wasFetchedViaServiceWorker()) { // It's still possible to reach here with null m_fallbackRequestForServiceWorker // if the request was for main resource loading (i.e. for SharedWorker), for which // we create DocumentLoader before the controller ServiceWorker is set. ASSERT(!m_fallbackRequestForServiceWorker.isNull() || m_requestContext == WebURLRequest::RequestContextSharedWorker); if (response.wasFallbackRequiredByServiceWorker()) { // At this point we must have m_fallbackRequestForServiceWorker. // (For SharedWorker the request won't be CORS or CORS-with-preflight, // therefore fallback-to-network is handled in the browser process // when the ServiceWorker does not call respondWith().) ASSERT(!m_fallbackRequestForServiceWorker.isNull()); reportResponseReceived(identifier, response); loadFallbackRequestForServiceWorker(); // |this| may be dead here in async mode. return; } m_fallbackRequestForServiceWorker = ResourceRequest(); m_client->didReceiveResponse(identifier, response, handle); return; } // Even if the request met the conditions to get handled by a Service Worker // in the constructor of this class (and therefore // |m_fallbackRequestForServiceWorker| is set), the Service Worker may skip // processing the request. Only if the request is same origin, the skipped // response may come here (wasFetchedViaServiceWorker() returns false) since // such a request doesn't have to go through the CORS algorithm by calling // loadFallbackRequestForServiceWorker(). // FIXME: We should use |m_sameOriginRequest| when we will support // Suborigins (crbug.com/336894) for Service Worker. ASSERT(m_fallbackRequestForServiceWorker.isNull() || securityOrigin()->canRequest(m_fallbackRequestForServiceWorker.url())); m_fallbackRequestForServiceWorker = ResourceRequest(); if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessControl) { String accessControlErrorDescription; if (!passesAccessControlCheck(response, effectiveAllowCredentials(), securityOrigin(), accessControlErrorDescription, m_requestContext)) { reportResponseReceived(identifier, response); ThreadableLoaderClient* client = m_client; clear(); client->didFailAccessControlCheck(ResourceError(errorDomainBlinkInternal, 0, response.url().string(), accessControlErrorDescription)); // |this| may be dead here. return; } } m_client->didReceiveResponse(identifier, response, handle); }
void SecurityContext::enforceSandboxFlags(SandboxFlags mask) { m_sandboxFlags |= mask; // The SandboxOrigin is stored redundantly in the security origin. if (isSandboxed(SandboxOrigin) && securityOrigin() && !securityOrigin()->isUnique()) setSecurityOrigin(SecurityOrigin::createUnique()); }
void WorkerContext::databaseExceededQuota(const String&) { #if !PLATFORM(CHROMIUM) // FIXME: This needs a real implementation; this is a temporary solution for testing. const unsigned long long defaultQuota = 5 * 1024 * 1024; #if ENABLE(GROUP_BASED_DATABASE) DatabaseTracker::tracker(groupName()).setQuota(securityOrigin(), defaultQuota); #else DatabaseTracker::tracker().setQuota(securityOrigin(), defaultQuota); #endif #endif }
bool Geolocation::shouldBlockGeolocationRequests() { bool isSecure = SecurityOrigin::isSecure(document()->url()); bool hasMixedContent = !document()->foundMixedContent().isEmpty(); bool isLocalOrigin = securityOrigin()->isLocal(); if (securityOrigin()->canRequestGeolocation()) { if (isLocalOrigin || (isSecure && !hasMixedContent) || isRequestFromIBooks()) return false; } logError(securityOrigin()->toString(), isSecure, hasMixedContent, document()); return true; }
bool ScriptExecutionContext::dispatchErrorEvent(const String& errorMessage, int lineNumber, const String& sourceURL) { EventTarget* target = errorEventTarget(); if (!target) return false; String message; int line; String sourceName; KURL targetUrl = completeURL(sourceURL); if (securityOrigin()->canRequest(targetUrl)) { message = errorMessage; line = lineNumber; sourceName = sourceURL; } else { message = "Script error."; sourceName = String(); line = 0; } ASSERT(!m_inDispatchErrorEvent); m_inDispatchErrorEvent = true; RefPtr<ErrorEvent> errorEvent = ErrorEvent::create(message, sourceName, line); target->dispatchEvent(errorEvent); m_inDispatchErrorEvent = false; return errorEvent->defaultPrevented(); }
// Implements the getUserMedia method from http://www.whatwg.org/specs/web-apps/current-work/#dom-navigator-getusermedia. void MediaStreamFrameController::generateStream(const String& options, PassRefPtr<NavigatorUserMediaSuccessCallback> successCallback, PassRefPtr<NavigatorUserMediaErrorCallback> errorCallback, ExceptionCode& ec) { ec = 0; if (!successCallback) return; GenerateStreamOptionFlags flags = parseGenerateStreamOptions(options); if (!flags) { ec = NOT_SUPPORTED_ERR; return; } int requestId = m_requests.getNextId(); m_requests.add(requestId, GenerateStreamRequest::create(scriptExecutionContext(), successCallback, errorCallback)); if (!isClientAvailable()) { // This makes sure to call the error callback if provided. m_requests.abort(requestId); return; } pageController()->generateStream(this, requestId, flags, securityOrigin()); }
Document* XMLHttpRequest::responseXML(ExceptionCode& ec) { if (responseTypeCode() != ResponseTypeDefault && responseTypeCode() != ResponseTypeText && responseTypeCode() != ResponseTypeDocument) { ec = INVALID_STATE_ERR; return 0; } if (m_state != DONE) return 0; if (!m_createdDocument) { if ((m_response.isHTTP() && !responseIsXML()) || scriptExecutionContext()->isWorkerContext()) { // The W3C spec requires this. m_responseXML = 0; } else { m_responseXML = Document::create(0, m_url); // FIXME: Set Last-Modified. m_responseXML->setContent(m_responseBuilder.toStringPreserveCapacity()); m_responseXML->setSecurityOrigin(securityOrigin()); if (!m_responseXML->wellFormed()) m_responseXML = 0; } m_createdDocument = true; } return m_responseXML.get(); }
PassRefPtr<EntrySync> WorkerContext::webkitResolveLocalFileSystemSyncURL(const String& url, ExceptionCode& ec) { ec = 0; KURL completedURL = completeURL(url); if (!AsyncFileSystem::isAvailable() || !securityOrigin()->canAccessFileSystem() || !securityOrigin()->canRequest(completedURL)) { ec = FileException::SECURITY_ERR; return 0; } AsyncFileSystem::Type type; String filePath; if (!completedURL.isValid() || !DOMFileSystemBase::crackFileSystemURL(completedURL, type, filePath)) { ec = FileException::ENCODING_ERR; return 0; } FileSystemSyncCallbackHelper readFileSystemHelper; LocalFileSystem::localFileSystem().readFileSystem(this, type, FileSystemCallbacks::create(readFileSystemHelper.successCallback(), readFileSystemHelper.errorCallback(), this), true); RefPtr<DOMFileSystemSync> fileSystem = readFileSystemHelper.getResult(ec); if (!fileSystem) return 0; RefPtr<EntrySync> entry = fileSystem->root()->getDirectory(filePath, 0, ec); if (ec == FileException::TYPE_MISMATCH_ERR) return fileSystem->root()->getFile(filePath, 0, ec); return entry.release(); }
TEST(MixedContentCheckerTest, IsMixedContent) { struct TestCase { const char* origin; const char* target; bool expectation; } cases[] = { {"http://example.com/foo", "http://example.com/foo", false}, {"http://example.com/foo", "https://example.com/foo", false}, {"https://example.com/foo", "https://example.com/foo", false}, {"https://example.com/foo", "wss://example.com/foo", false}, {"https://example.com/foo", "http://example.com/foo", true}, {"https://example.com/foo", "http://google.com/foo", true}, {"https://example.com/foo", "ws://example.com/foo", true}, {"https://example.com/foo", "ws://google.com/foo", true}, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) { const char* origin = cases[i].origin; const char* target = cases[i].target; bool expectation = cases[i].expectation; KURL originUrl(KURL(), origin); RefPtr<SecurityOrigin> securityOrigin(SecurityOrigin::create(originUrl)); KURL targetUrl(KURL(), target); EXPECT_EQ(expectation, MixedContentChecker::isMixedContent(securityOrigin.get(), targetUrl)) << "Origin: " << origin << ", Target: " << target << ", Expectation: " << expectation; } }
bool DocumentThreadableLoader::isAllowedRedirect(const URL& url) { if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) return true; return m_sameOriginRequest && securityOrigin()->canRequest(url); }
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); }
TEST(MixedContentCheckerTest, IsMixedContent) { struct TestCase { const char* origin; const char* target; bool expectation; } cases[] = { {"http://example.com/foo", "http://example.com/foo", false}, {"http://example.com/foo", "https://example.com/foo", false}, {"http://example.com/foo", "data:text/html,<p>Hi!</p>", false}, {"http://example.com/foo", "about:blank", false}, {"https://example.com/foo", "https://example.com/foo", false}, {"https://example.com/foo", "wss://example.com/foo", false}, {"https://example.com/foo", "data:text/html,<p>Hi!</p>", false}, {"https://example.com/foo", "http://127.0.0.1/", false}, {"https://example.com/foo", "http://[::1]/", false}, {"https://example.com/foo", "http://example.com/foo", true}, {"https://example.com/foo", "http://google.com/foo", true}, {"https://example.com/foo", "ws://example.com/foo", true}, {"https://example.com/foo", "ws://google.com/foo", true}, {"https://example.com/foo", "http://192.168.1.1/", true}, {"https://example.com/foo", "http://localhost/", true}, }; for (const auto& test : cases) { SCOPED_TRACE(::testing::Message() << "Origin: " << test.origin << ", Target: " << test.target << ", Expectation: " << test.expectation); KURL originUrl(KURL(), test.origin); RefPtr<SecurityOrigin> securityOrigin(SecurityOrigin::create(originUrl)); KURL targetUrl(KURL(), test.target); EXPECT_EQ(test.expectation, MixedContentChecker::isMixedContent(securityOrigin.get(), targetUrl)); } }
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); }
Document* XMLHttpRequest::responseXML(ExceptionCode& ec) { if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) { ec = INVALID_STATE_ERR; return nullptr; } if (!doneWithoutErrors()) return nullptr; if (!m_createdDocument) { bool isHTML = equalIgnoringCase(responseMIMEType(), "text/html"); // The W3C spec requires the final MIME type to be some valid XML type, or text/html. // If it is text/html, then the responseType of "document" must have been supplied explicitly. if ((m_response.isHTTP() && !responseIsXML() && !isHTML) || (isHTML && m_responseTypeCode == ResponseTypeDefault) || scriptExecutionContext()->isWorkerGlobalScope()) { m_responseDocument = 0; } else { if (isHTML) m_responseDocument = HTMLDocument::create(0, m_url); else m_responseDocument = Document::create(0, m_url); // FIXME: Set Last-Modified. m_responseDocument->setContent(m_responseBuilder.toStringPreserveCapacity()); m_responseDocument->setSecurityOrigin(securityOrigin()); if (!m_responseDocument->wellFormed()) m_responseDocument = 0; } m_createdDocument = true; } return m_responseDocument.get(); }
virtual void fire(Frame& frame) override { UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProcessingUserGesture : DefinitelyNotProcessingUserGesture); ResourceRequest resourceRequest(url(), referrer(), ReloadIgnoringCacheData); FrameLoadRequest frameRequest(securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Allow, m_shouldOpenExternalURLsPolicy); frame.loader().changeLocation(frameRequest); }
void Database::reportExecuteStatementResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode) { if (Platform::current()->databaseObserver()) { Platform::current()->databaseObserver()->reportExecuteStatementResult( createDatabaseIdentifierFromSecurityOrigin(securityOrigin()), stringIdentifier(), errorSite, webSqlErrorCode, sqliteErrorCode); } }
void Database::reportVacuumDatabaseResult(int sqliteErrorCode) { if (Platform::current()->databaseObserver()) { Platform::current()->databaseObserver()->reportVacuumDatabaseResult( createDatabaseIdentifierFromSecurityOrigin(securityOrigin()), stringIdentifier(), sqliteErrorCode); } }
virtual void fire(Frame* frame) { OwnPtr<UserGestureIndicator> gestureIndicator = createUserGestureIndicator(); FrameLoadRequest request(securityOrigin(), ResourceRequest(KURL(ParsedURLString, url()), referrer(), ReloadIgnoringCacheData), "_self"); request.setLockBackForwardList(lockBackForwardList()); request.setClientRedirect(ClientRedirect); frame->loader().load(request); }
PassRefPtr<DatabaseSync> WorkerContext::openDatabaseSync(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode& ec) { if (!securityOrigin()->canAccessDatabase() || !AbstractDatabase::isAvailable()) { ec = SECURITY_ERR; return 0; } return DatabaseSync::openDatabaseSync(this, name, version, displayName, estimatedSize, creationCallback, ec); }
bool ScriptExecutionContext::sanitizeScriptError(String& errorMessage, int& lineNumber, int& columnNumber, String& sourceURL, Deprecated::ScriptValue& error, CachedScript* cachedScript) { ASSERT(securityOrigin()); if (cachedScript) { ASSERT(cachedScript->origin()); ASSERT(securityOrigin()->toString() == cachedScript->origin()->toString()); if (cachedScript->isCORSSameOrigin()) return false; } else if (securityOrigin()->canRequest(completeURL(sourceURL))) return false; errorMessage = "Script error."; sourceURL = String(); lineNumber = 0; columnNumber = 0; error = Deprecated::ScriptValue(); return true; }
KURL ScriptExecutionContext::createPublicBlobURL(Blob* blob) { if (!blob) return KURL(); KURL publicURL = BlobURL::createPublicURL(securityOrigin()); ThreadableBlobRegistry::registerBlobURL(publicURL, blob->url()); m_publicBlobURLs.add(publicURL.string()); return publicURL; }
bool ScriptExecutionContext::sanitizeScriptError(String& errorMessage, int& lineNumber, int& columnNumber, String& sourceURL, JSC::Strong<JSC::Unknown>& error, CachedScript* cachedScript) { ASSERT(securityOrigin()); if (cachedScript) { ASSERT(cachedScript->origin()); ASSERT(securityOrigin()->toString() == cachedScript->origin()->toString()); if (cachedScript->isCORSSameOrigin()) return false; } else if (securityOrigin()->canRequest(completeURL(sourceURL))) return false; errorMessage = ASCIILiteral { "Script error." }; sourceURL = { }; lineNumber = 0; columnNumber = 0; error = { }; return true; }
void fire(Frame& frame) override { UserGestureIndicator gestureIndicator(wasUserGesture() ? DefinitelyProcessingUserGesture : DefinitelyNotProcessingUserGesture); bool refresh = equalIgnoringFragmentIdentifier(frame.document()->url(), url()); ResourceRequest resourceRequest(url(), referrer(), refresh ? ReloadIgnoringCacheData : UseProtocolCachePolicy); FrameLoadRequest frameRequest(securityOrigin(), resourceRequest, "_self", lockHistory(), lockBackForwardList(), MaybeSendReferrer, AllowNavigationToInvalidURL::No, NewFrameOpenerPolicy::Allow, m_shouldOpenExternalURLsPolicy); frame.loader().changeLocation(frameRequest); }
// These are used to generate histograms of errors seen with websql. // See about:histograms in chromium. void Database::reportOpenDatabaseResult(int errorSite, int webSqlErrorCode, int sqliteErrorCode, double duration) { if (Platform::current()->databaseObserver()) { Platform::current()->databaseObserver()->reportOpenDatabaseResult( createDatabaseIdentifierFromSecurityOrigin(securityOrigin()), stringIdentifier(), errorSite, webSqlErrorCode, sqliteErrorCode, duration); } }
void ContentSecurityPolicy::applyPolicySideEffectsToExecutionContext() { ASSERT(m_executionContext); ASSERT(securityOrigin()); // Ensure that 'self' processes correctly. m_selfProtocol = securityOrigin()->protocol(); m_selfSource = adoptPtr(new CSPSource(this, m_selfProtocol, securityOrigin()->host(), securityOrigin()->port(), String(), CSPSource::NoWildcard, CSPSource::NoWildcard)); if (didSetReferrerPolicy()) m_executionContext->setReferrerPolicy(m_referrerPolicy); // If we're in a Document, set mixed content checking and sandbox // flags, then dump all the parsing error messages, then poke at histograms. if (Document* document = this->document()) { if (m_sandboxMask != SandboxNone) { UseCounter::count(document, UseCounter::SandboxViaCSP); document->enforceSandboxFlags(m_sandboxMask); } if (m_enforceStrictMixedContentChecking) document->enforceStrictMixedContentChecking(); if (RuntimeEnabledFeatures::suboriginsEnabled()) { document->enforceSuborigin(m_suboriginName); } if (m_insecureRequestsPolicy == SecurityContext::InsecureRequestsUpgrade) { UseCounter::count(document, UseCounter::UpgradeInsecureRequestsEnabled); document->setInsecureRequestsPolicy(m_insecureRequestsPolicy); if (!securityOrigin()->host().isNull()) document->addInsecureNavigationUpgrade(securityOrigin()->host().impl()->hash()); } for (const auto& consoleMessage : m_consoleMessages) m_executionContext->addConsoleMessage(consoleMessage); m_consoleMessages.clear(); for (const auto& policy : m_policies) UseCounter::count(*document, getUseCounterType(policy->headerType())); } // We disable 'eval()' even in the case of report-only policies, and rely on the check in the // V8Initializer::codeGenerationCheckCallbackInMainThread callback to determine whether the // call should execute or not. if (!m_disableEvalErrorMessage.isNull()) m_executionContext->disableEval(m_disableEvalErrorMessage); }
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); } } }