| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "bindings/core/v8/WindowProxy.h" | 31 #include "bindings/core/v8/WindowProxy.h" |
| 32 | 32 |
| 33 #include <utility> | 33 #include <utility> |
| 34 | 34 |
| 35 #include "bindings/core/v8/V8Binding.h" | |
| 36 #include "bindings/core/v8/V8DOMWrapper.h" | 35 #include "bindings/core/v8/V8DOMWrapper.h" |
| 37 #include "bindings/core/v8/V8GCForContextDispose.h" | |
| 38 #include "bindings/core/v8/V8PagePopupControllerBinding.h" | |
| 39 #include "core/frame/DOMWindow.h" | |
| 40 #include "core/frame/Frame.h" | 36 #include "core/frame/Frame.h" |
| 41 #include "v8/include/v8.h" | 37 #include "v8/include/v8.h" |
| 42 #include "wtf/Assertions.h" | 38 #include "wtf/Assertions.h" |
| 43 | 39 |
| 44 namespace blink { | 40 namespace blink { |
| 45 | 41 |
| 46 WindowProxy::~WindowProxy() { | 42 WindowProxy::~WindowProxy() { |
| 47 // clearForClose() or clearForNavigation() must be invoked before destruction | 43 // clearForClose() or clearForNavigation() must be invoked before destruction |
| 48 // starts. | 44 // starts. |
| 49 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); | 45 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); |
| 50 } | 46 } |
| 51 | 47 |
| 52 DEFINE_TRACE(WindowProxy) { | 48 DEFINE_TRACE(WindowProxy) { |
| 53 visitor->trace(m_frame); | 49 visitor->trace(m_frame); |
| 54 } | 50 } |
| 55 | 51 |
| 56 WindowProxy::WindowProxy(v8::Isolate* isolate, | 52 WindowProxy::WindowProxy(v8::Isolate* isolate, |
| 57 Frame& frame, | 53 Frame& frame, |
| 58 RefPtr<DOMWrapperWorld> world) | 54 RefPtr<DOMWrapperWorld> world) |
| 59 : m_isolate(isolate), | 55 : m_isolate(isolate), |
| 60 m_frame(frame), | 56 m_frame(frame), |
| 61 | 57 |
| 62 m_world(std::move(world)), | 58 m_world(std::move(world)), |
| 63 m_lifecycle(Lifecycle::ContextUninitialized) {} | 59 m_lifecycle(Lifecycle::ContextUninitialized) {} |
| 64 | 60 |
| 65 void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior) { | |
| 66 DCHECK(m_lifecycle == Lifecycle::ContextInitialized); | |
| 67 | |
| 68 if (behavior == DetachGlobal) { | |
| 69 v8::Local<v8::Context> context = m_scriptState->context(); | |
| 70 // Clean up state on the global proxy, which will be reused. | |
| 71 if (!m_globalProxy.isEmpty()) { | |
| 72 // TODO(yukishiino): This DCHECK failed on Canary (M57) and Dev (M56). | |
| 73 // We need to figure out why m_globalProxy != context->Global(). | |
| 74 DCHECK(m_globalProxy == context->Global()); | |
| 75 DCHECK_EQ(toScriptWrappable(context->Global()), | |
| 76 toScriptWrappable( | |
| 77 context->Global()->GetPrototype().As<v8::Object>())); | |
| 78 m_globalProxy.get().SetWrapperClassId(0); | |
| 79 } | |
| 80 V8DOMWrapper::clearNativeInfo(m_isolate, context->Global()); | |
| 81 m_scriptState->detachGlobalObject(); | |
| 82 } | |
| 83 | |
| 84 m_scriptState->disposePerContextData(); | |
| 85 | |
| 86 // It's likely that disposing the context has created a lot of | |
| 87 // garbage. Notify V8 about this so it'll have a chance of cleaning | |
| 88 // it up when idle. | |
| 89 V8GCForContextDispose::instance().notifyContextDisposed( | |
| 90 m_frame->isMainFrame()); | |
| 91 | |
| 92 DCHECK(m_lifecycle == Lifecycle::ContextInitialized); | |
| 93 m_lifecycle = Lifecycle::ContextDetached; | |
| 94 } | |
| 95 | |
| 96 void WindowProxy::clearForClose() { | 61 void WindowProxy::clearForClose() { |
| 97 disposeContext(DoNotDetachGlobal); | 62 disposeContext(DoNotDetachGlobal); |
| 98 } | 63 } |
| 99 | 64 |
| 100 void WindowProxy::clearForNavigation() { | 65 void WindowProxy::clearForNavigation() { |
| 101 disposeContext(DetachGlobal); | 66 disposeContext(DetachGlobal); |
| 102 } | 67 } |
| 103 | 68 |
| 104 v8::Local<v8::Object> WindowProxy::globalIfNotDetached() { | 69 v8::Local<v8::Object> WindowProxy::globalIfNotDetached() { |
| 105 if (m_lifecycle == Lifecycle::ContextInitialized) { | 70 if (m_lifecycle == Lifecycle::ContextInitialized) |
| 106 DCHECK(m_scriptState->contextIsValid()); | |
| 107 DCHECK(m_globalProxy == m_scriptState->context()->Global()); | |
| 108 return m_globalProxy.newLocal(m_isolate); | 71 return m_globalProxy.newLocal(m_isolate); |
| 109 } | |
| 110 return v8::Local<v8::Object>(); | 72 return v8::Local<v8::Object>(); |
| 111 } | 73 } |
| 112 | 74 |
| 113 v8::Local<v8::Object> WindowProxy::releaseGlobal() { | 75 v8::Local<v8::Object> WindowProxy::releaseGlobal() { |
| 114 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); | 76 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); |
| 115 // Make sure the global object was detached from the proxy by calling | 77 DLOG_IF(FATAL, m_isGlobalProxyAttached) |
| 116 // clearForNavigation(). | 78 << "Context not detached by calling clearForNavigation()"; |
| 117 if (m_lifecycle == Lifecycle::ContextDetached) | |
| 118 ASSERT(m_scriptState->isGlobalObjectDetached()); | |
| 119 | 79 |
| 120 v8::Local<v8::Object> global = m_globalProxy.newLocal(m_isolate); | 80 v8::Local<v8::Object> global = m_globalProxy.newLocal(m_isolate); |
| 121 m_globalProxy.clear(); | 81 m_globalProxy.clear(); |
| 122 return global; | 82 return global; |
| 123 } | 83 } |
| 124 | 84 |
| 125 void WindowProxy::setGlobal(v8::Local<v8::Object> global) { | 85 void WindowProxy::setGlobal(v8::Local<v8::Object> global) { |
| 126 m_globalProxy.set(m_isolate, global); | 86 m_globalProxy.set(m_isolate, global); |
| 127 | 87 |
| 128 // Initialize the window proxy now, to re-establish the connection between | 88 // Initialize the window proxy now, to re-establish the connection between |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 // If there are JS code holds a closure to the old inner window, | 130 // If there are JS code holds a closure to the old inner window, |
| 171 // it won't be able to reach the outer window via its global object. | 131 // it won't be able to reach the outer window via its global object. |
| 172 void WindowProxy::initializeIfNeeded() { | 132 void WindowProxy::initializeIfNeeded() { |
| 173 // TODO(haraken): It is wrong to re-initialize an already detached window | 133 // TODO(haraken): It is wrong to re-initialize an already detached window |
| 174 // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'. | 134 // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'. |
| 175 if (m_lifecycle != Lifecycle::ContextInitialized) { | 135 if (m_lifecycle != Lifecycle::ContextInitialized) { |
| 176 initialize(); | 136 initialize(); |
| 177 } | 137 } |
| 178 } | 138 } |
| 179 | 139 |
| 180 void WindowProxy::setupWindowPrototypeChain() { | |
| 181 // Associate the window wrapper object and its prototype chain with the | |
| 182 // corresponding native DOMWindow object. | |
| 183 // The full structure of the global object's prototype chain is as follows: | |
| 184 // | |
| 185 // global proxy object [1] | |
| 186 // -- has prototype --> global object (window wrapper object) [2] | |
| 187 // -- has prototype --> Window.prototype | |
| 188 // -- has prototype --> WindowProperties [3] | |
| 189 // -- has prototype --> EventTarget.prototype | |
| 190 // -- has prototype --> Object.prototype | |
| 191 // -- has prototype --> null | |
| 192 // | |
| 193 // [1] Global proxy object is as known as "outer global object". It's an | |
| 194 // empty object and remains after navigation. When navigated, points to | |
| 195 // a different global object as the prototype object. | |
| 196 // [2] Global object is as known as "inner global object" or "window wrapper | |
| 197 // object". The prototype chain between global proxy object and global | |
| 198 // object is NOT observable from user JavaScript code. All other | |
| 199 // prototype chains are observable. Global proxy object and global object | |
| 200 // together appear to be the same single JavaScript object. See also: | |
| 201 // https://wiki.mozilla.org/Gecko:SplitWindow | |
| 202 // global object (= window wrapper object) provides most of Window's DOM | |
| 203 // attributes and operations. Also global variables defined by user | |
| 204 // JavaScript are placed on this object. When navigated, a new global | |
| 205 // object is created together with a new v8::Context, but the global proxy | |
| 206 // object doesn't change. | |
| 207 // [3] WindowProperties is a named properties object of Window interface. | |
| 208 | |
| 209 DOMWindow* window = m_frame->domWindow(); | |
| 210 const WrapperTypeInfo* wrapperTypeInfo = window->wrapperTypeInfo(); | |
| 211 v8::Local<v8::Context> context = m_scriptState->context(); | |
| 212 | |
| 213 // The global proxy object. Note this is not the global object. | |
| 214 v8::Local<v8::Object> globalProxy = context->Global(); | |
| 215 CHECK(m_globalProxy == globalProxy); | |
| 216 V8DOMWrapper::setNativeInfo(m_isolate, globalProxy, wrapperTypeInfo, window); | |
| 217 // Mark the handle to be traced by Oilpan, since the global proxy has a | |
| 218 // reference to the DOMWindow. | |
| 219 m_globalProxy.get().SetWrapperClassId(wrapperTypeInfo->wrapperClassId); | |
| 220 | |
| 221 // The global object, aka window wrapper object. | |
| 222 v8::Local<v8::Object> windowWrapper = | |
| 223 globalProxy->GetPrototype().As<v8::Object>(); | |
| 224 windowWrapper = V8DOMWrapper::associateObjectWithWrapper( | |
| 225 m_isolate, window, wrapperTypeInfo, windowWrapper); | |
| 226 | |
| 227 // The prototype object of Window interface. | |
| 228 v8::Local<v8::Object> windowPrototype = | |
| 229 windowWrapper->GetPrototype().As<v8::Object>(); | |
| 230 CHECK(!windowPrototype.IsEmpty()); | |
| 231 V8DOMWrapper::setNativeInfo(m_isolate, windowPrototype, wrapperTypeInfo, | |
| 232 window); | |
| 233 | |
| 234 // The named properties object of Window interface. | |
| 235 v8::Local<v8::Object> windowProperties = | |
| 236 windowPrototype->GetPrototype().As<v8::Object>(); | |
| 237 CHECK(!windowProperties.IsEmpty()); | |
| 238 V8DOMWrapper::setNativeInfo(m_isolate, windowProperties, wrapperTypeInfo, | |
| 239 window); | |
| 240 | |
| 241 // TODO(keishi): Remove installPagePopupController and implement | |
| 242 // PagePopupController in another way. | |
| 243 V8PagePopupControllerBinding::installPagePopupController(context, | |
| 244 windowWrapper); | |
| 245 } | |
| 246 | |
| 247 } // namespace blink | 140 } // namespace blink |
| OLD | NEW |