void V8Proxy::clearForNavigation()
{
resetIsolatedWorlds();
-<<<<<<< HEAD
-
- if (!m_context.IsEmpty()) {
- v8::HandleScope handle;
- clearDocumentWrapper();
-
- v8::Context::Scope contextScope(m_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.
- clearDocumentWrapperCache();
-
- // Turn on access check on the old DOMWindow wrapper.
- v8::Handle<v8::Object> wrapper = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::DOMWINDOW, m_global);
- ASSERT(!wrapper.IsEmpty());
- wrapper->TurnOnAccessCheck();
-
- // Separate the context from its global object.
- m_context->DetachGlobal();
-
- disposeContextHandles();
- }
-}
-
-void V8Proxy::setSecurityToken()
-{
- Document* document = m_frame->document();
- // Setup security origin and security token.
- if (!document) {
- m_context->UseDefaultSecurityToken();
- return;
- }
-
- // Ask the document's SecurityOrigin to generate a security token.
- // If two tokens are equal, then the SecurityOrigins canAccess each other.
- // If two tokens are not equal, then we have to call canAccess.
- // Note: we can't use the HTTPOrigin if it was set from the DOM.
- SecurityOrigin* origin = document->securityOrigin();
- String token;
- if (!origin->domainWasSetInDOM())
- token = document->securityOrigin()->toString();
-
- // An empty or "null" token means we always have to call
- // canAccess. The toString method on securityOrigins returns the
- // string "null" for empty security origins and for security
- // origins that should only allow access to themselves. In this
- // case, we use the global object as the security token to avoid
- // calling canAccess when a script accesses its own objects.
- if (token.isEmpty() || token == "null") {
- m_context->UseDefaultSecurityToken();
- return;
- }
-
- CString utf8Token = token.utf8();
- // NOTE: V8 does identity comparison in fast path, must use a symbol
- // as the security token.
- m_context->SetSecurityToken(v8::String::NewSymbol(utf8Token.data(), utf8Token.length()));
-}
-
-void V8Proxy::updateDocument()
-{
- if (!m_frame->document())
- return;
-
- if (m_global.IsEmpty())
- return;
-
- // There is an existing JavaScript wrapper for the global object
- // of this frame. JavaScript code in other frames might hold a
- // reference to this wrapper. We eagerly initialize the JavaScript
- // context for the new document to make property access on the
- // global object wrapper succeed.
- initContextIfNeeded();
-
- // Bail out if context initialization failed.
- if (m_context.IsEmpty())
- return;
-
- // We have a new document and we need to update the cache.
- updateDocumentWrapperCache();
-
- updateSecurityOrigin();
-}
-
-void V8Proxy::updateSecurityOrigin()
-{
- v8::HandleScope scope;
- setSecurityToken();
-}
-
-// Same origin policy implementation:
-//
-// Same origin policy prevents JS code from domain A access JS & DOM objects
-// in a different domain B. There are exceptions and several objects are
-// accessible by cross-domain code. For example, the window.frames object is
-// accessible by code from a different domain, but window.document is not.
-//
-// The binding code sets security check callbacks on a function template,
-// and accessing instances of the template calls the callback function.
-// The callback function checks same origin policy.
-//
-// Callback functions are expensive. V8 uses a security token string to do
-// fast access checks for the common case where source and target are in the
-// same domain. A security token is a string object that represents
-// the protocol/url/port of a domain.
-//
-// There are special cases where a security token matching is not enough.
-// For example, JavaScript can set its domain to a super domain by calling
-// document.setDomain(...). In these cases, the binding code can reset
-// a context's security token to its global object so that the fast access
-// check will always fail.
-
-// Check if the current execution context can access a target frame.
-// First it checks same domain policy using the lexical context
-//
-// This is equivalent to KJS::Window::allowsAccessFrom(ExecState*, String&).
-bool V8Proxy::canAccessPrivate(DOMWindow* targetWindow)
-{
- ASSERT(targetWindow);
-
- String message;
-
- v8::Local<v8::Context> activeContext = v8::Context::GetCalling();
- if (activeContext.IsEmpty()) {
- // There is a single activation record on the stack, so that must
- // be the activeContext.
- activeContext = v8::Context::GetCurrent();
- }
- DOMWindow* activeWindow = retrieveWindow(activeContext);
- if (activeWindow == targetWindow)
- return true;
-
- if (!activeWindow)
- return false;
-
- const SecurityOrigin* activeSecurityOrigin = activeWindow->securityOrigin();
- const SecurityOrigin* targetSecurityOrigin = targetWindow->securityOrigin();
-
- // We have seen crashes were the security origin of the target has not been
- // initialized. Defend against that.
- if (!targetSecurityOrigin)
- return false;
-
- if (activeSecurityOrigin->canAccess(targetSecurityOrigin))
- return true;
-
- // Allow access to a "about:blank" page if the dynamic context is a
- // detached context of the same frame as the blank page.
- if (targetSecurityOrigin->isEmpty() && activeWindow->frame() == targetWindow->frame())
- return true;
-
- return false;
-}
-
-bool V8Proxy::canAccessFrame(Frame* target, bool reportError)
-{
- // The subject is detached from a frame, deny accesses.
- if (!target)
- return false;
-
- if (!canAccessPrivate(target->domWindow())) {
- if (reportError)
- reportUnsafeAccessTo(target, ReportNow);
- return false;
- }
- return true;
-}
-
-bool V8Proxy::checkNodeSecurity(Node* node)
-{
- if (!node)
- return false;
-
- Frame* target = node->document()->frame();
-
- if (!target)
- return false;
-
- return canAccessFrame(target, true);
-}
-
-v8::Persistent<v8::Context> V8Proxy::createNewContext(v8::Handle<v8::Object> global, int extensionGroup)
-{
- v8::Persistent<v8::Context> result;
-
- // The activeDocumentLoader pointer could be NULL during frame shutdown.
- if (!m_frame->loader()->activeDocumentLoader())
- return result;
-
- // Create a new environment using an empty template for the shadow
- // object. Reuse the global object if one has been created earlier.
- v8::Persistent<v8::ObjectTemplate> globalTemplate = V8DOMWindow::GetShadowObjectTemplate();
- if (globalTemplate.IsEmpty())
- return result;
-
- // Install a security handler with V8.
- globalTemplate->SetAccessCheckCallbacks(V8Custom::v8DOMWindowNamedSecurityCheck, V8Custom::v8DOMWindowIndexedSecurityCheck, v8::Integer::New(V8ClassIndex::DOMWINDOW));
- globalTemplate->SetInternalFieldCount(V8Custom::kDOMWindowInternalFieldCount);
-
- // Used to avoid sleep calls in unload handlers.
- if (!registeredExtensionWithV8(DateExtension::get()))
- registerExtension(DateExtension::get(), String());
-
- // Dynamically tell v8 about our extensions now.
- OwnArrayPtr<const char*> extensionNames(new const char*[m_extensions.size()]);
- int index = 0;
- for (size_t i = 0; i < m_extensions.size(); ++i) {
- if (m_extensions[i].group && m_extensions[i].group != extensionGroup)
- continue;
-
- // Note: we check the loader URL here instead of the document URL
- // because we might be currently loading an URL into a blank page.
- // See http://code.google.com/p/chromium/issues/detail?id=10924
- if (m_extensions[i].scheme.length() > 0 && (m_extensions[i].scheme != m_frame->loader()->activeDocumentLoader()->url().protocol() || m_extensions[i].scheme != m_frame->page()->mainFrame()->loader()->activeDocumentLoader()->url().protocol()))
- continue;
-
- extensionNames[index++] = m_extensions[i].extension->name();
- }
- v8::ExtensionConfiguration extensions(index, extensionNames.get());
- result = v8::Context::New(&extensions, globalTemplate, global);
-
- return result;
-}
-
-bool V8Proxy::installDOMWindow(v8::Handle<v8::Context> context, DOMWindow* window)
-{
- v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__");
- if (implicitProtoString.IsEmpty())
- return false;
-
- // Create a new JS window object and use it as the prototype for the shadow global object.
- v8::Handle<v8::Function> windowConstructor = V8DOMWrapper::getConstructor(V8ClassIndex::DOMWINDOW, getHiddenObjectPrototype(context));
- v8::Local<v8::Object> jsWindow = SafeAllocation::newInstance(windowConstructor);
- // Bail out if allocation failed.
- if (jsWindow.IsEmpty())
- return false;
-
- // Wrap the window.
- V8DOMWrapper::setDOMWrapper(jsWindow, V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
- V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(jsWindow->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
-
- window->ref();
- V8DOMWrapper::setJSWrapperForDOMObject(window, v8::Persistent<v8::Object>::New(jsWindow));
-
- // Insert the window instance as the prototype of the shadow object.
- v8::Handle<v8::Object> v8Global = context->Global();
- V8DOMWrapper::setDOMWrapper(v8::Handle<v8::Object>::Cast(v8Global->GetPrototype()), V8ClassIndex::ToInt(V8ClassIndex::DOMWINDOW), window);
- v8Global->Set(implicitProtoString, jsWindow);
- return 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.
-void V8Proxy::initContextIfNeeded()
-{
- // Bail out if the context has already been initialized.
- if (!m_context.IsEmpty())
- return;
-
-#ifdef ANDROID_INSTRUMENT
- android::TimeCounter::start(android::TimeCounter::JavaScriptInitTimeCounter);
-#endif
- // 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;
-
- 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;
- }
-#ifndef NDEBUG
- V8GCController::registerGlobalHandle(PROXY, this, m_global);
-#endif
- }
-
- installHiddenObjectPrototype(v8Context);
- 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(v8Context, m_frame->domWindow()))
- disposeContextHandles();
-
- 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);
-
-#ifdef ANDROID_INSTRUMENT
- android::TimeCounter::record(android::TimeCounter::JavaScriptInitTimeCounter, __FUNCTION__);
-#endif
-=======
windowShell()->clearForNavigation();
->>>>>>> webkit.org at r54127
}
void V8Proxy::setDOMException(int exceptionCode)