bool WindowProxy::initialize() { TRACE_EVENT0("v8", "WindowProxy::initialize"); SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.Binding.InitializeWindowProxy"); ScriptForbiddenScope::AllowUserAgentScript allowScript; v8::HandleScope handleScope(m_isolate); createContext(); if (!isContextInitialized()) return false; ScriptState::Scope scope(m_scriptState.get()); v8::Local<v8::Context> context = m_scriptState->context(); if (m_global.isEmpty()) { m_global.set(m_isolate, context->Global()); if (m_global.isEmpty()) { disposeContext(DoNotDetachGlobal); return false; } } if (!setupWindowPrototypeChain()) { disposeContext(DoNotDetachGlobal); return false; } SecurityOrigin* origin = 0; if (m_world->isMainWorld()) { // ActivityLogger for main world is updated within updateDocument(). updateDocument(); origin = m_frame->securityContext()->getSecurityOrigin(); // FIXME: Can this be removed when CSP moves to browser? ContentSecurityPolicy* csp = m_frame->securityContext()->contentSecurityPolicy(); context->AllowCodeGenerationFromStrings( csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); context->SetErrorMessageForCodeGenerationFromStrings( v8String(m_isolate, csp->evalDisabledErrorMessage())); } else { updateActivityLogger(); origin = m_world->isolatedWorldSecurityOrigin(); setSecurityToken(origin); } // All interfaces must be registered to V8PerContextData. // So we explicitly call constructorForType for the global object. V8PerContextData::from(context)->constructorForType( &V8Window::wrapperTypeInfo); if (m_frame->isLocalFrame()) { LocalFrame* frame = toLocalFrame(m_frame); MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), frame, origin); frame->loader().client()->didCreateScriptContext( context, m_world->extensionGroup(), m_world->worldId()); } return true; }
bool WindowProxy::initialize() { TRACE_EVENT0("v8", "WindowProxy::initialize"); TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "InitializeWindow"); SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.Binding.InitializeWindowProxy"); ScriptForbiddenScope::AllowUserAgentScript allowScript; v8::HandleScope handleScope(m_isolate); createContext(); if (!isContextInitialized()) return false; ScriptState::Scope scope(m_scriptState.get()); v8::Local<v8::Context> context = m_scriptState->context(); if (m_global.isEmpty()) { m_global.set(m_isolate, context->Global()); if (m_global.isEmpty()) { disposeContext(DoNotDetachGlobal); return false; } } if (!setupWindowPrototypeChain()) { disposeContext(DoNotDetachGlobal); return false; } SecurityOrigin* origin = 0; if (m_world->isMainWorld()) { // ActivityLogger for main world is updated within updateDocument(). updateDocument(); origin = m_frame->securityContext()->getSecurityOrigin(); // FIXME: Can this be removed when CSP moves to browser? ContentSecurityPolicy* csp = m_frame->securityContext()->contentSecurityPolicy(); context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage())); } else { updateActivityLogger(); origin = m_world->isolatedWorldSecurityOrigin(); setSecurityToken(origin); } if (m_frame->isLocalFrame()) { LocalFrame* frame = toLocalFrame(m_frame); MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), frame, origin); frame->loader().client()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId()); } // If Origin Trials have been registered before the V8 context was ready, // then inject them into the context now ExecutionContext* executionContext = m_scriptState->getExecutionContext(); if (executionContext) { OriginTrialContext* originTrialContext = OriginTrialContext::from(executionContext); if (originTrialContext) originTrialContext->initializePendingFeatures(); } return true; }
bool WindowProxy::initialize() { TRACE_EVENT0("v8", "WindowProxy::initialize"); TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "InitializeWindow"); ScriptForbiddenScope::AllowUserAgentScript allowScript; v8::HandleScope handleScope(m_isolate); createContext(); if (!isContextInitialized()) return false; ScriptState::Scope scope(m_scriptState.get()); v8::Local<v8::Context> context = m_scriptState->context(); if (m_global.isEmpty()) { m_global.set(m_isolate, context->Global()); if (m_global.isEmpty()) { disposeContext(DoNotDetachGlobal); return false; } } if (!installDOMWindow()) { disposeContext(DoNotDetachGlobal); return false; } SecurityOrigin* origin = 0; if (m_world->isMainWorld()) { // ActivityLogger for main world is updated within updateDocument(). updateDocument(); origin = m_frame->securityContext()->securityOrigin(); // FIXME: Can this be removed when CSP moves to browser? ContentSecurityPolicy* csp = m_frame->securityContext()->contentSecurityPolicy(); context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage())); } else { updateActivityLogger(); origin = m_world->isolatedWorldSecurityOrigin(); setSecurityToken(origin); } if (m_frame->isLocalFrame()) { LocalFrame* frame = toLocalFrame(m_frame); MainThreadDebugger::initializeContext(context, m_world->worldId()); InspectorInstrumentation::didCreateScriptContext(frame, m_scriptState.get(), origin, m_world->worldId()); frame->loader().client()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId()); } return true; }
bool ContentSecurityPolicy::allowPluginTypeForDocument(const Document& document, const String& type, const String& typeAttribute, const KURL& url, ContentSecurityPolicy::ReportingStatus reportingStatus) const { if (document.contentSecurityPolicy() && !document.contentSecurityPolicy()->allowPluginType(type, typeAttribute, url)) return false; // CSP says that a plugin document in a nested browsing context should // inherit the plugin-types of its parent. // // FIXME: The plugin-types directive should be pushed down into the // current document instead of reaching up to the parent for it here. LocalFrame* frame = document.frame(); if (frame && frame->tree().parent() && frame->tree().parent()->isLocalFrame() && document.isPluginDocument()) { ContentSecurityPolicy* parentCSP = toLocalFrame(frame->tree().parent())->document()->contentSecurityPolicy(); if (parentCSP && !parentCSP->allowPluginType(type, typeAttribute, url)) return false; } return true; }
static bool isAllowed(ScriptState* scriptState, ExecutionContext* executionContext, bool isEval) { if (executionContext->isDocument()) { Document* document = static_cast<Document*>(executionContext); if (isEval && !document->contentSecurityPolicy()->allowEval(scriptState, ContentSecurityPolicy::SendReport, ContentSecurityPolicy::WillNotThrowException)) return false; return true; } if (executionContext->isWorkerGlobalScope()) { WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(executionContext); if (!workerGlobalScope->script()) return false; ContentSecurityPolicy* policy = workerGlobalScope->contentSecurityPolicy(); if (isEval && policy && !policy->allowEval(scriptState, ContentSecurityPolicy::SendReport, ContentSecurityPolicy::WillNotThrowException)) return false; return true; } ASSERT_NOT_REACHED(); return false; }
void WorkerMessagingProxy::startWorkerGlobalScope(const KURL& scriptURL, const String& userAgent, const String& sourceCode, WorkerThreadStartMode startMode) { // FIXME: This need to be revisited when we support nested worker one day ASSERT(m_executionContext->isDocument()); if (m_askedToTerminate) { // Worker.terminate() could be called from JS before the thread was created. return; } Document* document = toDocument(m_executionContext.get()); SecurityOrigin* starterOrigin = document->securityOrigin(); ContentSecurityPolicy* csp = m_workerObject->contentSecurityPolicy() ? m_workerObject->contentSecurityPolicy() : document->contentSecurityPolicy(); ASSERT(csp); OwnPtr<WorkerThreadStartupData> startupData = WorkerThreadStartupData::create(scriptURL, userAgent, sourceCode, nullptr, startMode, csp->headers(), starterOrigin, m_workerClients.release()); double originTime = document->loader() ? document->loader()->timing().referenceMonotonicTime() : monotonicallyIncreasingTime(); m_loaderProxy = WorkerLoaderProxy::create(this); RefPtr<WorkerThread> thread = createWorkerThread(originTime); thread->start(startupData.release()); workerThreadCreated(thread); m_workerInspectorProxy->workerThreadCreated(m_executionContext.get(), m_workerThread.get(), scriptURL); }
// Create a new environment and setup the global object. // // The global object corresponds to a DOMWindow instance. However, to // allow properties of the JS DOMWindow instance to be shadowed, we // use a shadow object as the global object and use the JS DOMWindow // instance as the prototype for that shadow object. The JS DOMWindow // instance is undetectable from JavaScript code because the __proto__ // accessors skip that object. // // The shadow object and the DOMWindow instance are seen as one object // from JavaScript. The JavaScript object that corresponds to a // DOMWindow instance is the shadow object. When mapping a DOMWindow // instance to a V8 object, we return the shadow object. // // To implement split-window, see // 1) https://bugs.webkit.org/show_bug.cgi?id=17249 // 2) https://wiki.mozilla.org/Gecko:SplitWindow // 3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639 // we need to split the shadow object further into two objects: // an outer window and an inner window. The inner window is the hidden // prototype of the outer window. The inner window is the default // global object of the context. A variable declared in the global // scope is a property of the inner window. // // The outer window sticks to a Frame, it is exposed to JavaScript // via window.window, window.self, window.parent, etc. The outer window // has a security token which is the domain. The outer window cannot // have its own properties. window.foo = 'x' is delegated to the // inner window. // // When a frame navigates to a new page, the inner window is cut off // the outer window, and the outer window identify is preserved for // the frame. However, a new inner window is created for the new page. // If there are JS code holds a closure to the old inner window, // it won't be able to reach the outer window via its global object. bool V8WindowShell::initializeIfNeeded() { if (m_contextHolder) return true; TRACE_EVENT0("v8", "V8WindowShell::initializeIfNeeded"); v8::HandleScope handleScope(m_isolate); createContext(); if (!m_contextHolder) return false; v8::Handle<v8::Context> context = m_contextHolder->context(); V8PerContextDataHolder::install(context); m_world->setIsolatedWorldField(context); bool isMainWorld = m_world->isMainWorld(); v8::Context::Scope contextScope(context); if (m_global.isEmpty()) { m_global.set(m_isolate, context->Global()); if (m_global.isEmpty()) { disposeContext(DoNotDetachGlobal); return false; } } if (!isMainWorld) { V8WindowShell* mainWindow = m_frame->script().existingWindowShell(mainThreadNormalWorld()); if (mainWindow && !mainWindow->context().IsEmpty()) setInjectedScriptContextDebugId(context, m_frame->script().contextDebugId(mainWindow->context())); } m_perContextData = V8PerContextData::create(context); if (!m_perContextData->init()) { disposeContext(DoNotDetachGlobal); return false; } m_perContextData->setActivityLogger(DOMWrapperWorld::activityLogger(m_world->worldId())); if (!installDOMWindow()) { disposeContext(DoNotDetachGlobal); return false; } if (isMainWorld) { updateDocument(); setSecurityToken(); if (m_frame->document()) { ContentSecurityPolicy* csp = m_frame->document()->contentSecurityPolicy(); context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage())); } } else { // Using the default security token means that the canAccess is always // called, which is slow. // FIXME: Use tokens where possible. This will mean keeping track of all // created contexts so that they can all be updated when the // document domain // changes. context->UseDefaultSecurityToken(); SecurityOrigin* origin = m_world->isolatedWorldSecurityOrigin(); if (origin && InspectorInstrumentation::hasFrontends()) { ScriptState* scriptState = ScriptState::forContext(v8::Local<v8::Context>::New(m_isolate, context)); InspectorInstrumentation::didCreateIsolatedContext(m_frame, scriptState, origin); } } m_frame->loader().client()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId()); return true; }
void WebSharedWorkerImpl::onScriptLoaderFinished() { DCHECK(m_loadingDocument); DCHECK(m_mainScriptLoader); if (m_askedToTerminate) return; if (m_mainScriptLoader->failed()) { m_mainScriptLoader->cancel(); m_client->workerScriptLoadFailed(); // The SharedWorker was unable to load the initial script, so // shut it down right here. delete this; return; } Document* document = m_mainFrame->frame()->document(); // FIXME: this document's origin is pristine and without any extra privileges. // (crbug.com/254993) SecurityOrigin* starterOrigin = document->getSecurityOrigin(); WorkerClients* workerClients = WorkerClients::create(); provideLocalFileSystemToWorker(workerClients, LocalFileSystemClient::create()); WebSecurityOrigin webSecurityOrigin(m_loadingDocument->getSecurityOrigin()); provideContentSettingsClientToWorker( workerClients, wrapUnique( m_client->createWorkerContentSettingsClientProxy(webSecurityOrigin))); provideIndexedDBClientToWorker(workerClients, IndexedDBClientImpl::create()); ContentSecurityPolicy* contentSecurityPolicy = m_mainScriptLoader->releaseContentSecurityPolicy(); WorkerThreadStartMode startMode = m_workerInspectorProxy->workerStartMode(document); std::unique_ptr<WorkerSettings> workerSettings = wrapUnique(new WorkerSettings(document->settings())); std::unique_ptr<WorkerThreadStartupData> startupData = WorkerThreadStartupData::create( m_url, m_loadingDocument->userAgent(), m_mainScriptLoader->script(), nullptr, startMode, contentSecurityPolicy ? contentSecurityPolicy->headers().get() : nullptr, m_mainScriptLoader->referrerPolicy(), starterOrigin, workerClients, m_mainScriptLoader->responseAddressSpace(), m_mainScriptLoader->originTrialTokens(), std::move(workerSettings)); // We have a dummy document here for loading but it doesn't really represent // the document/frame of associated document(s) for this worker. Here we // populate the task runners with null document not to confuse the frame // scheduler (which will end up using the thread's default task runner). m_mainThreadTaskRunners = ParentFrameTaskRunners::create(nullptr); m_loaderProxy = WorkerLoaderProxy::create(this); m_workerThread = SharedWorkerThread::create(m_name, m_loaderProxy, *this); InspectorInstrumentation::scriptImported(m_loadingDocument.get(), m_mainScriptLoader->identifier(), m_mainScriptLoader->script()); m_mainScriptLoader.clear(); workerThread()->start(std::move(startupData)); m_workerInspectorProxy->workerThreadCreated( toDocument(m_loadingDocument.get()), workerThread(), m_url); m_client->workerScriptLoaded(); }