shared_ptr<ScopedVariableContext> ScopedVariableEnvironment::createNewDefaultContext(){ shared_ptr<ScopedVariableContext> new_context = createNewContext(); for(int i = 0; i < variables.getNElements(); i++){ shared_ptr<ScopedVariable> var = variables[i]; auto props = var->getProperties(); new_context->set(var->getContextIndex(), props->getDefaultValue()); } return new_context; }
void V8Proxy::evaluateInNewContext(const Vector<ScriptSourceCode>& sources, int extensionGroup) { initContextIfNeeded(); v8::HandleScope handleScope; // Set up the DOM window as the prototype of the new global object. v8::Handle<v8::Context> windowContext = context(); v8::Handle<v8::Object> windowGlobal = windowContext->Global(); v8::Handle<v8::Object> windowWrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, windowGlobal); ASSERT(V8DOMWrapper::convertDOMWrapperToNative<DOMWindow>(windowWrapper) == m_frame->domWindow()); v8::Persistent<v8::Context> context = createNewContext(v8::Handle<v8::Object>(), extensionGroup); v8::Context::Scope contextScope(context); // Setup context id for JS debugger. v8::Handle<v8::Object> contextData = v8::Object::New(); v8::Handle<v8::Value> windowContextData = windowContext->GetData(); if (windowContextData->IsObject()) { v8::Handle<v8::String> propertyName = v8::String::New(kContextDebugDataValue); contextData->Set(propertyName, v8::Object::Cast(*windowContextData)->Get(propertyName)); } contextData->Set(v8::String::New(kContextDebugDataType), v8::String::New("injected")); context->SetData(contextData); v8::Handle<v8::Object> global = context->Global(); v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__"); global->Set(implicitProtoString, windowWrapper); // Give the code running in the new context a way to get access to the // original context. global->Set(v8::String::New("contentWindow"), windowGlobal); m_frame->loader()->client()->didCreateIsolatedScriptContext(); // Run code in the new context. for (size_t i = 0; i < sources.size(); ++i) evaluate(sources[i], 0); // 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(); context.Dispose(); }
// 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. void V8Proxy::initContextIfNeeded() { // Bail out if the context has already been initialized. if (!context().IsEmpty()) return; // Create a handle scope for all local handles. v8::HandleScope handleScope; // Setup the security handlers and message listener. This only has // to be done once. static bool isV8Initialized = false; if (!isV8Initialized) { // Tells V8 not to call the default OOM handler, binding code // will handle it. v8::V8::IgnoreOutOfMemoryException(); v8::V8::SetFatalErrorHandler(reportFatalErrorInV8); v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue); v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue); v8::V8::AddMessageListener(&V8ConsoleMessage::handler); v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess); isV8Initialized = true; } v8::Persistent<v8::Context> context = createNewContext(m_global, 0); if (context.IsEmpty()) return; m_context->set(context); v8::Context::Scope contextScope(context); // Store the first global object created so we can reuse it. if (m_global.IsEmpty()) { m_global = v8::Persistent<v8::Object>::New(context->Global()); // Bail out if allocation of the first global objects fails. if (m_global.IsEmpty()) { disposeContextHandles(); return; } #ifndef NDEBUG V8GCController::registerGlobalHandle(PROXY, this, m_global); #endif } installHiddenObjectPrototype(context); m_wrapperBoilerplates = v8::Persistent<v8::Array>::New(v8::Array::New(V8ClassIndex::WRAPPER_TYPE_COUNT)); // Bail out if allocation failed. if (m_wrapperBoilerplates.IsEmpty()) { disposeContextHandles(); return; } #ifndef NDEBUG V8GCController::registerGlobalHandle(PROXY, this, m_wrapperBoilerplates); #endif if (!installDOMWindow(context, m_frame->domWindow())) disposeContextHandles(); updateDocument(); setSecurityToken(); m_frame->loader()->client()->didCreateScriptContextForFrame(); m_frame->loader()->dispatchWindowObjectAvailable(); }
// 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::initContextIfNeeded() { // Bail out if the context has already been initialized. if (!m_context.IsEmpty()) return false; // Create a handle scope for all local handles. v8::HandleScope handleScope; // Setup the security handlers and message listener. This only has // to be done once. static bool isV8Initialized = false; if (!isV8Initialized) { // Tells V8 not to call the default OOM handler, binding code // will handle it. v8::V8::IgnoreOutOfMemoryException(); v8::V8::SetFatalErrorHandler(reportFatalErrorInV8); v8::V8::SetGlobalGCPrologueCallback(&V8GCController::gcPrologue); v8::V8::SetGlobalGCEpilogueCallback(&V8GCController::gcEpilogue); v8::V8::AddMessageListener(&V8ConsoleMessage::handler); v8::V8::SetFailedAccessCheckCallbackFunction(reportUnsafeJavaScriptAccess); isV8Initialized = true; } m_context = createNewContext(m_global, 0); if (m_context.IsEmpty()) return false; v8::Local<v8::Context> v8Context = v8::Local<v8::Context>::New(m_context); v8::Context::Scope contextScope(v8Context); // Store the first global object created so we can reuse it. if (m_global.IsEmpty()) { m_global = v8::Persistent<v8::Object>::New(v8Context->Global()); // Bail out if allocation of the first global objects fails. if (m_global.IsEmpty()) { disposeContextHandles(); return false; } #ifndef NDEBUG V8GCController::registerGlobalHandle(PROXY, this, m_global); #endif } if (!installHiddenObjectPrototype(v8Context)) { disposeContextHandles(); return false; } if (!installDOMWindow(v8Context, m_frame->domWindow())) { disposeContextHandles(); return false; } updateDocument(); setSecurityToken(); m_frame->loader()->client()->didCreateScriptContextForFrame(); // FIXME: This is wrong. We should actually do this for the proper world once // we do isolated worlds the WebCore way. m_frame->loader()->dispatchDidClearWindowObjectInWorld(0); return true; }