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