Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
void WindowProxy::clearForClose()
{
    if (!isContextInitialized())
        return;

    disposeContext(DoNotDetachGlobal);
}
Пример #6
0
void WindowProxy::clearForNavigation() {
  if (!isContextInitialized())
    return;

  ScriptState::Scope scope(m_scriptState.get());

  disposeContext(DetachGlobal);
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #9
0
void V8DOMWindowShell::clearForClose()
{
    if (m_context.isEmpty())
        return;

    v8::HandleScope handleScope;
    m_document.clear();
    disposeContext();
}
Пример #10
0
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();
}
Пример #12
0
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();
}
Пример #14
0
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()));
}
Пример #15
0
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);
}
Пример #16
0
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);
}
Пример #17
0
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();
}
Пример #18
0
// 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;
}
Пример #19
0
void V8DOMWindowShell::destroyIsolatedShell()
{
    disposeContext(true);
}
Пример #20
0
// 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;
}