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" | |
34 #include "bindings/core/v8/V8DOMWrapper.h" | 33 #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" | |
38 #include "core/frame/Frame.h" | 34 #include "core/frame/Frame.h" |
39 #include "wtf/Assertions.h" | 35 #include "wtf/Assertions.h" |
40 #include <utility> | 36 #include <utility> |
41 #include <v8.h> | 37 #include <v8.h> |
42 | 38 |
43 namespace blink { | 39 namespace blink { |
44 | 40 |
45 WindowProxy::~WindowProxy() { | 41 WindowProxy::~WindowProxy() { |
46 // clearForClose() or clearForNavigation() must be invoked before destruction | 42 // clearForClose() or clearForNavigation() must be invoked before destruction |
47 // starts. | 43 // starts. |
48 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); | 44 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); |
49 } | 45 } |
50 | 46 |
51 DEFINE_TRACE(WindowProxy) { | 47 DEFINE_TRACE(WindowProxy) { |
52 visitor->trace(m_frame); | 48 visitor->trace(m_frame); |
53 } | 49 } |
54 | 50 |
55 WindowProxy::WindowProxy(v8::Isolate* isolate, | 51 WindowProxy::WindowProxy(v8::Isolate* isolate, |
56 Frame& frame, | 52 Frame& frame, |
57 RefPtr<DOMWrapperWorld> world) | 53 RefPtr<DOMWrapperWorld> world) |
58 : m_isolate(isolate), | 54 : m_isolate(isolate), |
59 m_frame(frame), | 55 m_frame(frame), |
60 | 56 |
61 m_world(std::move(world)), | 57 m_world(std::move(world)), |
62 m_lifecycle(Lifecycle::ContextUninitialized) {} | 58 m_lifecycle(Lifecycle::ContextUninitialized) {} |
63 | 59 |
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 | |
95 void WindowProxy::clearForClose() { | 60 void WindowProxy::clearForClose() { |
96 disposeContext(DoNotDetachGlobal); | 61 disposeContext(DoNotDetachGlobal); |
97 } | 62 } |
98 | 63 |
99 void WindowProxy::clearForNavigation() { | 64 void WindowProxy::clearForNavigation() { |
100 disposeContext(DetachGlobal); | 65 disposeContext(DetachGlobal); |
101 } | 66 } |
102 | 67 |
103 v8::Local<v8::Object> WindowProxy::globalIfNotDetached() { | 68 v8::Local<v8::Object> WindowProxy::globalIfNotDetached() { |
104 if (m_lifecycle == Lifecycle::ContextInitialized) { | 69 if (m_lifecycle == Lifecycle::ContextInitialized) |
105 DCHECK(m_scriptState->contextIsValid()); | |
106 DCHECK(m_globalProxy == m_scriptState->context()->Global()); | |
107 return m_globalProxy.newLocal(m_isolate); | 70 return m_globalProxy.newLocal(m_isolate); |
108 } | |
109 return v8::Local<v8::Object>(); | 71 return v8::Local<v8::Object>(); |
110 } | 72 } |
111 | 73 |
112 v8::Local<v8::Object> WindowProxy::releaseGlobal() { | 74 v8::Local<v8::Object> WindowProxy::releaseGlobal() { |
113 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); | 75 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); |
114 // Make sure the global object was detached from the proxy by calling | 76 DLOG_IF(FATAL, m_isGlobalProxyAttached) |
115 // clearForNavigation(). | 77 << "Context not detached by calling clearForNavigation()"; |
116 if (m_lifecycle == Lifecycle::ContextDetached) | |
117 ASSERT(m_scriptState->isGlobalObjectDetached()); | |
118 | 78 |
119 v8::Local<v8::Object> global = m_globalProxy.newLocal(m_isolate); | 79 v8::Local<v8::Object> global = m_globalProxy.newLocal(m_isolate); |
120 m_globalProxy.clear(); | 80 m_globalProxy.clear(); |
121 return global; | 81 return global; |
122 } | 82 } |
123 | 83 |
124 void WindowProxy::setGlobal(v8::Local<v8::Object> global) { | 84 void WindowProxy::setGlobal(v8::Local<v8::Object> global) { |
125 m_globalProxy.set(m_isolate, global); | 85 m_globalProxy.set(m_isolate, global); |
126 | 86 |
127 // Initialize the window proxy now, to re-establish the connection between | 87 // Initialize the window proxy now, to re-establish the connection between |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
169 // If there are JS code holds a closure to the old inner window, | 129 // If there are JS code holds a closure to the old inner window, |
170 // it won't be able to reach the outer window via its global object. | 130 // it won't be able to reach the outer window via its global object. |
171 void WindowProxy::initializeIfNeeded() { | 131 void WindowProxy::initializeIfNeeded() { |
172 // TODO(haraken): It is wrong to re-initialize an already detached window | 132 // TODO(haraken): It is wrong to re-initialize an already detached window |
173 // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'. | 133 // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'. |
174 if (m_lifecycle != Lifecycle::ContextInitialized) { | 134 if (m_lifecycle != Lifecycle::ContextInitialized) { |
175 initialize(); | 135 initialize(); |
176 } | 136 } |
177 } | 137 } |
178 | 138 |
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 | |
246 } // namespace blink | 139 } // namespace blink |
OLD | NEW |