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"); ScriptForbiddenScope::AllowUserAgentScript allowScript; v8::HandleScope handleScope(m_isolate); createContext(); if (!isContextInitialized()) return false; ScriptState::Scope scope(m_scriptState.get()); v8::Handle<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; } updateDocument(); m_frame->loaderClient()->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; }
void WindowProxy::clearForClose() { if (!isContextInitialized()) return; disposeContext(DoNotDetachGlobal); }
void WindowProxy::clearForNavigation() { if (!isContextInitialized()) return; ScriptState::Scope scope(m_scriptState.get()); disposeContext(DetachGlobal); }
bool WorkerScriptController::initializeContextIfNeeded() { if (m_contextHolder) return true; v8::Handle<v8::Context> context = v8::Context::New(isolate()); if (context.IsEmpty()) return false; m_contextHolder = adoptPtr(new gin::ContextHolder(isolate())); m_contextHolder->SetContext(context); v8::Context::Scope scope(context); V8PerContextDataHolder::install(context, m_world.get()); m_perContextData = V8PerContextData::create(context); if (!m_perContextData->init()) { disposeContext(); return false; } // Set DebugId for the new context. context->SetEmbedderData(0, v8AtomicString(isolate(), "worker")); // Create a new JS object and use it as the prototype for the shadow global object. const WrapperTypeInfo* contextType = &V8DedicatedWorkerGlobalScope::wrapperTypeInfo; if (m_workerGlobalScope.isServiceWorkerGlobalScope()) contextType = &V8ServiceWorkerGlobalScope::wrapperTypeInfo; else if (!m_workerGlobalScope.isDedicatedWorkerGlobalScope()) contextType = &V8SharedWorkerGlobalScope::wrapperTypeInfo; v8::Handle<v8::Function> workerGlobalScopeConstructor = m_perContextData->constructorForType(contextType); v8::Local<v8::Object> jsWorkerGlobalScope = V8ObjectConstructor::newInstance(workerGlobalScopeConstructor); if (jsWorkerGlobalScope.IsEmpty()) { disposeContext(); return false; } V8DOMWrapper::associateObjectWithWrapper<V8WorkerGlobalScope>(PassRefPtr<WorkerGlobalScope>(m_workerGlobalScope), contextType, jsWorkerGlobalScope, isolate(), WrapperConfiguration::Dependent); // Insert the object instance as the prototype of the shadow object. v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_contextHolder->context()->Global()->GetPrototype()); globalObject->SetPrototype(jsWorkerGlobalScope); return true; }
bool WorkerScriptController::initializeContextIfNeeded() { if (!m_context.isEmpty()) return true; v8::Persistent<v8::ObjectTemplate> globalTemplate; m_context.adopt(v8::Context::New(0, globalTemplate)); if (m_context.isEmpty()) return false; // Starting from now, use local context only. v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context.get()); v8::Context::Scope scope(context); m_perContextData = V8PerContextData::create(m_context.get()); if (!m_perContextData->init()) { disposeContext(); return false; } // Set DebugId for the new context. context->SetEmbedderData(0, v8::String::NewSymbol("worker")); // Create a new JS object and use it as the prototype for the shadow global object. WrapperTypeInfo* contextType = &V8DedicatedWorkerContext::info; #if ENABLE(SHARED_WORKERS) if (!m_workerContext->isDedicatedWorkerContext()) contextType = &V8SharedWorkerContext::info; #endif v8::Handle<v8::Function> workerContextConstructor = m_perContextData->constructorForType(contextType); v8::Local<v8::Object> jsWorkerContext = V8ObjectConstructor::newInstance(workerContextConstructor); if (jsWorkerContext.IsEmpty()) { disposeContext(); return false; } V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<WorkerContext>(m_workerContext), contextType, jsWorkerContext, m_isolate); // Insert the object instance as the prototype of the shadow object. v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_context->Global()->GetPrototype()); globalObject->SetPrototype(jsWorkerContext); return true; }
void V8DOMWindowShell::clearForClose() { if (m_context.isEmpty()) return; v8::HandleScope handleScope; m_document.clear(); disposeContext(); }
void V8WindowShell::clearForClose(bool destroyGlobal) { if (destroyGlobal) m_global.clear(); if (!m_contextHolder) return; m_document.clear(); disposeContext(DoNotDetachGlobal); }
void V8WindowShell::clearForClose(bool destroyGlobal) { if (destroyGlobal) m_global.clear(); if (m_context.isEmpty()) return; m_document.clear(); disposeContext(); }
void V8DOMWindowShell::destroyIsolatedShell() { ASSERT(m_world->isIsolatedWorld()); if (m_context.isEmpty()) return; v8::HandleScope handleScope; m_world->makeContextWeak(m_context.get()); disposeContext(); m_global.clear(); }
WorkerScriptController::~WorkerScriptController() { m_domDataStore.clear(); // The corresponding call to didStartWorkerRunLoop is in // WorkerThread::workerThread(). // See http://webkit.org/b/83104#c14 for why this is here. WebKit::Platform::current()->didStopWorkerRunLoop(WebKit::WebWorkerRunLoop(&m_workerGlobalScope->thread()->runLoop())); disposeContext(); V8PerIsolateData::dispose(m_isolate); m_isolate->Exit(); m_isolate->Dispose(); }
WorkerScriptController::~WorkerScriptController() { ThreadState::current()->removeInterruptor(m_interruptor.get()); RELEASE_ASSERT(m_world->hasOneRef()); // ~DOMWrapperWorld() must be called before disposing the isolate. m_world = nullptr; // The corresponding call to didStartWorkerRunLoop is in // WorkerThread::workerThread(). // See http://webkit.org/b/83104#c14 for why this is here. blink::Platform::current()->didStopWorkerRunLoop(blink::WebWorkerRunLoop(&m_workerGlobalScope.thread()->runLoop())); disposeContext(); ThreadState::current()->addCleanupTask(IsolateCleanupTask::create(m_isolateHolder.release())); }
void WindowProxy::clearForNavigation() { if (!isContextInitialized()) return; ScriptState::Scope scope(m_scriptState.get()); m_document.clear(); // Clear the document wrapper cache before turning on access checks on // the old LocalDOMWindow wrapper. This way, access to the document wrapper // will be protected by the security checks on the LocalDOMWindow wrapper. clearDocumentProperty(); v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(m_global.newLocal(m_isolate), m_isolate); ASSERT(!windowWrapper.IsEmpty()); windowWrapper->TurnOnAccessCheck(); disposeContext(DetachGlobal); }
void V8WindowShell::clearForNavigation() { if (!m_contextHolder) return; v8::HandleScope handleScope(m_isolate); m_document.clear(); v8::Handle<v8::Context> context = m_contextHolder->context(); v8::Context::Scope contextScope(context); // Clear the document wrapper cache before turning on access checks on // the old DOMWindow wrapper. This way, access to the document wrapper // will be protected by the security checks on the DOMWindow wrapper. clearDocumentProperty(); v8::Handle<v8::Object> windowWrapper = m_global.newLocal(m_isolate)->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate))); ASSERT(!windowWrapper.IsEmpty()); windowWrapper->TurnOnAccessCheck(); disposeContext(DetachGlobal); }
void V8DOMWindowShell::clearForNavigation() { if (m_context.isEmpty()) return; v8::HandleScope handleScope; m_document.clear(); // FIXME: Should we create a new Local handle here? v8::Context::Scope contextScope(m_context.get()); // Clear the document wrapper cache before turning on access checks on // the old DOMWindow wrapper. This way, access to the document wrapper // will be protected by the security checks on the DOMWindow wrapper. clearDocumentProperty(); v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8DOMWindow::GetTemplate(), m_global.get()); ASSERT(!windowWrapper.IsEmpty()); windowWrapper->TurnOnAccessCheck(); m_context->DetachGlobal(); disposeContext(); }
// 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 V8DOMWindowShell::initializeIfNeeded() { if (!m_context.isEmpty()) return true; v8::HandleScope handleScope; initializeV8IfNeeded(); createContext(); if (m_context.isEmpty()) return false; bool isMainWorld = m_world->isMainWorld(); v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context.get()); v8::Context::Scope contextScope(context); if (m_global.isEmpty()) { m_global.set(context->Global()); if (m_global.isEmpty()) { disposeContext(); return false; } } // Flag context as isolated. if (!isMainWorld) { V8DOMWindowShell* mainWindow = m_frame->script()->windowShell(); mainWindow->initializeIfNeeded(); if (!mainWindow->context().IsEmpty()) setInjectedScriptContextDebugId(m_context.get(), m_frame->script()->contextDebugId(mainWindow->context())); setIsolatedWorldField(this, context); } m_perContextData = V8PerContextData::create(m_context.get()); if (!m_perContextData->init()) { disposeContext(); return false; } if (!installDOMWindow()) { disposeContext(); return false; } if (isMainWorld) { updateDocument(); setSecurityToken(); if (m_frame->document()) context->AllowCodeGenerationFromStrings(m_frame->document()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport)); } 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. m_context->UseDefaultSecurityToken(); } m_frame->loader()->client()->didCreateScriptContext(m_context.get(), m_world->extensionGroup(), m_world->worldId()); if (isMainWorld) { // FIXME: This call is probably in the wrong spot, but causes a test timeout for http/tests/misc/window-open-then-write.html when removed. // Additionally, ScriptController::existingWindowShell cannot be correctly implemented until this call is gone. m_frame->loader()->dispatchDidClearWindowObjectInWorld(0); } return true; }
void V8DOMWindowShell::destroyIsolatedShell() { disposeContext(true); }
// 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; }