| /* |
| * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Google Inc. nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "bindings/core/v8/WindowProxy.h" |
| |
| #include <utility> |
| |
| #include "bindings/core/v8/V8DOMWrapper.h" |
| #include "core/frame/Frame.h" |
| #include "v8/include/v8.h" |
| #include "wtf/Assertions.h" |
| |
| namespace blink { |
| |
| WindowProxy::~WindowProxy() { |
| // clearForClose() or clearForNavigation() must be invoked before destruction |
| // starts. |
| DCHECK(m_lifecycle != Lifecycle::ContextInitialized); |
| } |
| |
| DEFINE_TRACE(WindowProxy) { |
| visitor->trace(m_frame); |
| } |
| |
| WindowProxy::WindowProxy(v8::Isolate* isolate, |
| Frame& frame, |
| RefPtr<DOMWrapperWorld> world) |
| : m_isolate(isolate), |
| m_frame(frame), |
| |
| m_world(std::move(world)), |
| m_lifecycle(Lifecycle::ContextUninitialized) {} |
| |
| void WindowProxy::clearForClose() { |
| disposeContext(DoNotDetachGlobal); |
| } |
| |
| void WindowProxy::clearForNavigation() { |
| disposeContext(DetachGlobal); |
| } |
| |
| v8::Local<v8::Object> WindowProxy::globalIfNotDetached() { |
| if (m_lifecycle == Lifecycle::ContextInitialized) |
| return m_globalProxy.newLocal(m_isolate); |
| return v8::Local<v8::Object>(); |
| } |
| |
| v8::Local<v8::Object> WindowProxy::releaseGlobal() { |
| DCHECK(m_lifecycle != Lifecycle::ContextInitialized); |
| DLOG_IF(FATAL, m_isGlobalProxyAttached) |
| << "Context not detached by calling clearForNavigation()"; |
| |
| v8::Local<v8::Object> global = m_globalProxy.newLocal(m_isolate); |
| m_globalProxy.clear(); |
| return global; |
| } |
| |
| void WindowProxy::setGlobal(v8::Local<v8::Object> global) { |
| m_globalProxy.set(m_isolate, global); |
| |
| // Initialize the window proxy now, to re-establish the connection between |
| // the global object and the v8::Context. This is really only needed for a |
| // RemoteDOMWindow, since it has no scripting environment of its own. |
| // Without this, existing script references to a swapped in RemoteDOMWindow |
| // would be broken until that RemoteDOMWindow was vended again through an |
| // interface like window.frames. |
| initializeIfNeeded(); |
| } |
| |
| // 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 LocalFrame, 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 WindowProxy::initializeIfNeeded() { |
| // TODO(haraken): It is wrong to re-initialize an already detached window |
| // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'. |
| if (m_lifecycle != Lifecycle::ContextInitialized) { |
| initialize(); |
| } |
| } |
| |
| } // namespace blink |