- V8WindowShell
- DOMWrapperWorld
- ScriptController
- Frame have ScriptController Object
- Who Call initializeMainWorld
V8WindowShell
V8WindowShell represents all the per-global object state for a Frame that persist between navigations.
Class Define
55 class V8WindowShell {
56 public:
57 static PassOwnPtr<V8WindowShell> create(Frame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*);
59 v8::Local<v8::Context> context() const { return m_context.newLocal(m_isolate); }
61 // Update document object of the frame.
62 void updateDocument();
80 DOMWrapperWorld* world() { return m_world.get(); }
82 private:
83 V8WindowShell(Frame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*);
85 void disposeContext();
95
96 void createContext();
97 bool installDOMWindow();
98
99 static V8WindowShell* enteredIsolatedWorldContext();
100
101 Frame* m_frame;
102 RefPtr<DOMWrapperWorld> m_world;
103 v8::Isolate* m_isolate;
104
105 OwnPtr<V8PerContextData> m_perContextData;
106
107 ScopedPersistent<v8::Context> m_context; // pay attention here ScopedPersistent for m_context.
108 ScopedPersistent<v8::Object> m_global; // also to m_global.
109 ScopedPersistent<v8::Object> m_document; // also to m_document.
110 };
Construct Function
We should provide a frame and world and isolate to construct it.
81 PassOwnPtr<V8WindowShell> V8WindowShell::create(Frame* frame, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate)
82 {
83 return adoptPtr(new V8WindowShell(frame, world, isolate));
84 }
85
86 V8WindowShell::V8WindowShell(Frame* frame, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate)
87 : m_frame(frame)
88 , m_world(world)
89 , m_isolate(isolate)
90 {
91 }
initializeIfNeeded
147 // Create a new environment and setup the global object.
148 //
149 // The global object corresponds to a DOMWindow instance. However, to
150 // allow properties of the JS DOMWindow instance to be shadowed, we
151 // use a shadow object as the global object and use the JS DOMWindow
152 // instance as the prototype for that shadow object. The JS DOMWindow
153 // instance is undetectable from JavaScript code because the __proto__
154 // accessors skip that object.
155 //
156 // The shadow object and the DOMWindow instance are seen as one object
157 // from JavaScript. The JavaScript object that corresponds to a
158 // DOMWindow instance is the shadow object. When mapping a DOMWindow
159 // instance to a V8 object, we return the shadow object.
160 //
161 // To implement split-window, see
162 // 1) https://bugs.webkit.org/show_bug.cgi?id=17249
163 // 2) https://wiki.mozilla.org/Gecko:SplitWindow
164 // 3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639
165 // we need to split the shadow object further into two objects:
166 // an outer window and an inner window. The inner window is the hidden
167 // prototype of the outer window. The inner window is the default
168 // global object of the context. A variable declared in the global
169 // scope is a property of the inner window.
170 //
171 // The outer window sticks to a Frame, it is exposed to JavaScript
172 // via window.window, window.self, window.parent, etc. The outer window
173 // has a security token which is the domain. The outer window cannot
174 // have its own properties. window.foo = 'x' is delegated to the
175 // inner window.
176 //
177 // When a frame navigates to a new page, the inner window is cut off
178 // the outer window, and the outer window identify is preserved for
179 // the frame. However, a new inner window is created for the new page.
180 // If there are JS code holds a closure to the old inner window,
181 // it won't be able to reach the outer window via its global object.
182 bool V8WindowShell::initializeIfNeeded()
183 {
184 if (!m_context.isEmpty())
185 return true;
186
187 v8::HandleScope handleScope(m_isolate);
188
189 V8Initializer::initializeMainThreadIfNeeded(m_isolate); //1.do v8 initialize.
190
191 createContext(); //2.create v8::Context.
192 if (m_context.isEmpty())
193 return false;
194
195 v8::Handle<v8::Context> context = m_context.newLocal(m_isolate);
196
197 m_world->setIsolatedWorldField(context);
199 bool isMainWorld = m_world->isMainWorld();
200
201 v8::Context::Scope contextScope(context);
202
203 if (m_global.isEmpty()) {
204 m_global.set(m_isolate, context->Global()); //3.get/set global set scope persist.
205 if (m_global.isEmpty()) {
206 disposeContext();
207 return false;
208 }
209 }
210
211 if (!isMainWorld) {
212 V8WindowShell* mainWindow = m_frame->script()->existingWindowShell(mainThreadNormalWorld());
213 if (mainWindow && !mainWindow->context().IsEmpty())
214 setInjectedScriptContextDebugId(context, m_frame->script()->contextDebugId(mainWindow->context()));
215 }
216
217 m_perContextData = V8PerContextData::create(context); //4.create V8PerContextData.
218 if (!m_perContextData->init()) {
219 disposeContext();
220 return false;
221 }
222 m_perContextData->setActivityLogger(DOMWrapperWorld::activityLogger(m_world->worldId()));
223 if (!installDOMWindow()) { //5.install dom window to context.
224 disposeContext();
225 return false;
226 }
227
228 if (isMainWorld) {
229 updateDocument(); //6.set docoument to context
230 setSecurityToken();
231 if (m_frame->document()) {
232 ContentSecurityPolicy* csp = m_frame->document()->contentSecurityPolicy();
233 context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurityPolicy::SuppressReport));
234 context->SetErrorMessageForCodeGenerationFromStrings(v8String(csp->evalDisabledErrorMessage(), m_isolate));
235 }
236 } else {
237 // Using the default security token means that the canAccess is always
238 // called, which is slow.
239 // FIXME: Use tokens where possible. This will mean keeping track of all
240 // created contexts so that they can all be updated when the
241 // document domain
242 // changes.
243 context->UseDefaultSecurityToken();
244
245 SecurityOrigin* origin = m_world->isolatedWorldSecurityOrigin();
246 if (origin && InspectorInstrumentation::hasFrontends()) {
247 ScriptState* scriptState = ScriptState::forContext(v8::Local<v8::Context>::New(context));
248 InspectorInstrumentation::didCreateIsolatedContext(m_frame, scriptState, origin);
249 }
250 }
251 m_frame->loader()->client()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId());
252 return true;
253 }
createContext
255 void V8WindowShell::createContext()
256 {
257 // The activeDocumentLoader pointer could be 0 during frame shutdown.
258 // FIXME: Can we remove this check?
259 if (!m_frame->loader()->activeDocumentLoader())
260 return;
261
262 // Create a new environment using an empty template for the shadow
263 // object. Reuse the global object if one has been created earlier.
264 v8::Handle<v8::ObjectTemplate> globalTemplate = V8Window::GetShadowObjectTemplate(m_isolate, m_world->isMainWorld() ? MainWorld : IsolatedWorld);
265 if (globalTemplate.IsEmpty())
266 return;
267
268 double contextCreationStartInSeconds = currentTime();
288 ..............................................................
289 v8::HandleScope handleScope(m_isolate);
290 m_context.set(m_isolate, v8::Context::New(m_isolate, &extensionConfiguration, globalTemplate, m_global.newLocal(m_isolate))); //pay attention to here, for how to v8::Context::New.
291
292 double contextCreationDurationInMilliseconds = (currentTime() - contextCreationStartInSeconds) * 1000;
293 const char* histogramName = "WebCore.V8WindowShell.createContext.MainWorld";
294 if (!m_world->isMainWorld())
295 histogramName = "WebCore.V8WindowShell.createContext.IsolatedWorld";
296 HistogramSupport::histogramCustomCounts(histogramName, contextCreationDurationInMilliseconds, 0, 10000, 50);
297 }
installDOMWindow
299 bool V8WindowShell::installDOMWindow()
300 {
301 DOMWrapperWorld::setInitializingWindow(true);
302 DOMWindow* window = m_frame->domWindow();
303 v8::Local<v8::Object> windowWrapper = V8ObjectConstructor::newInstance(V8PerContextData::from(m_context.newLocal(m_isolate))->constructorForType(&V8Window::info));
304 if (windowWrapper.IsEmpty()) // get real windowWrapper for DOMWindow.
305 return false;
306
307 V8Window::installPerContextProperties(windowWrapper, window, m_isolate);
308
309 V8DOMWrapper::setNativeInfo(v8::Handle<v8::Object>::Cast(windowWrapper->GetPrototype()), &V8Window::info, window);
310
311 // Install the windowWrapper as the prototype of the innerGlobalObject.
312 // The full structure of the global object is as follows:
313 //
314 // outerGlobalObject (Empty object, remains after navigation)
315 // -- has prototype --> innerGlobalObject (Holds global variables, changes during navigation)
316 // -- has prototype --> DOMWindow instance
317 // -- has prototype --> Window.prototype
318 // -- has prototype --> Object.prototype
319 //
320 // Note: Much of this prototype structure is hidden from web content. The
321 // outer, inner, and DOMWindow instance all appear to be the same
322 // JavaScript object.
323 //
324 v8::Handle<v8::Object> innerGlobalObject = toInnerGlobalObject(m_context.newLocal(m_isolate)); //v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype());
325 V8DOMWrapper::setNativeInfo(innerGlobalObject, &V8Window::info, window);
326 innerGlobalObject->SetPrototype(windowWrapper);//set windowWrapper as context->Global()'s prototype.
327 V8DOMWrapper::associateObjectWithWrapper<V8Window>(PassRefPtr<DOMWindow>(window), &V8Window::info, windowWrapper, m_isolate, WrapperConfiguration::Dependent);
328 DOMWrapperWorld::setInitializingWindow(false);
329 return true;
330 }
updateDocumentProperty
338 void V8WindowShell::updateDocumentProperty()
339 {
340 if (!m_world->isMainWorld())
341 return;
342
343 v8::HandleScope handleScope(m_isolate);
344 v8::Handle<v8::Context> context = m_context.newLocal(m_isolate);
345 v8::Context::Scope contextScope(context);
346
347 v8::Handle<v8::Value> documentWrapper = toV8(m_frame->document(), v8::Handle<v8::Object>(), context->GetIsolate());
348 ASSERT(documentWrapper == m_document.newLocal(m_isolate) || m_document.isEmpty());
349 if (m_document.isEmpty())
350 updateDocumentWrapper(v8::Handle<v8::Object>::Cast(documentWrapper));
351 checkDocumentWrapper(m_document.newLocal(m_isolate), m_frame->document());
352
353 // If instantiation of the document wrapper fails, clear the cache
354 // and let the DOMWindow accessor handle access to the document.
355 if (documentWrapper.IsEmpty()) {
356 clearDocumentProperty();
357 return;
358 }
359 ASSERT(documentWrapper->IsObject());
360 context->Global()->ForceSet(v8::String::NewSymbol("document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete));
361
362 // We also stash a reference to the document on the inner global object so that
363 // DOMWindow objects we obtain from JavaScript references are guaranteed to have
364 // live Document objects.
365 toInnerGlobalObject(context)->SetHiddenValue(V8HiddenPropertyName::document(), documentWrapper);
366 }
clearForClose
112 void V8WindowShell::clearForClose(bool destroyGlobal)
113 {
114 if (destroyGlobal)
115 m_global.clear();
116
117 if (m_context.isEmpty())
118 return;
119
120 m_document.clear();
121 disposeContext();
122 }
93 void V8WindowShell::disposeContext()
94 {
95 m_perContextData.clear();
96
97 if (m_context.isEmpty())
98 return;
99
100 v8::HandleScope handleScope(m_isolate);
101 m_frame->loader()->client()->willReleaseScriptContext(m_context.newLocal(m_isolate), m_world->worldId());
102
103 m_context.clear();
104
105 // It's likely that disposing the context has created a lot of
106 // garbage. Notify V8 about this so it'll have a chance of cleaning
107 // it up when idle.
108 bool isMainFrame = m_frame->page() && (m_frame->page()->mainFrame() == m_frame);
109 V8GCForContextDispose::instance().notifyContextDisposed(isMainFrame);
110 }
##V8PerContextData
Class Define
61 class V8PerContextData {
62 public:
63 static PassOwnPtr<V8PerContextData> create(v8::Handle<v8::Context> context)
64 {
65 return adoptPtr(new V8PerContextData(context));
66 }
68 ~V8PerContextData()
69 {
70 dispose();
71 }
73 bool init();
75 static V8PerContextData* from(v8::Handle<v8::Context> context)
76 {
77 return static_cast<V8PerContextData*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex));
78 }
79 ....................................................
89 v8::Local<v8::Function> constructorForType(WrapperTypeInfo* type)
90 {
91 UnsafePersistent<v8::Function> function = m_constructorMap.get(type);
92 if (!function.isEmpty())
93 return function.newLocal(v8::Isolate::GetCurrent());
94 return constructorForTypeSlowCase(type);
95 }
96 ...................................................
116 private:
117 explicit V8PerContextData(v8::Handle<v8::Context> context)
118 : m_activityLogger(0)
119 , m_isolate(v8::Isolate::GetCurrent())
120 , m_context(m_isolate, context) //m_context as v8::Persistent.
121 , m_customElementBindings(adoptPtr(new CustomElementBindingMap()))
122 {
123 }
124
125 void dispose();
134 ...................................................
135 typedef WTF::HashMap<WrapperTypeInfo*, UnsafePersistent<v8::Function> > ConstructorMap;
136 ConstructorMap m_constructorMap;
137
138 V8NPObjectMap m_v8NPObjectMap;
139 // We cache a pointer to the V8DOMActivityLogger associated with the world
140 // corresponding to this context. The ownership of the pointer is retained
141 // by the DOMActivityLoggerMap in DOMWrapperWorld.
142 V8DOMActivityLogger* m_activityLogger;
143 v8::Isolate* m_isolate;
144 v8::Persistent<v8::Context> m_context;
145 ScopedPersistent<v8::Value> m_errorPrototype;
146
147 typedef WTF::HashMap<CustomElementDefinition*, OwnPtr<CustomElementBinding> > CustomElementBindingMap;
148 OwnPtr<CustomElementBindingMap> m_customElementBindings;
149 };
init
61 #define V8_STORE_PRIMORDIAL(name, Name) \
62 { \
63 ASSERT(m_##name##Prototype.isEmpty()); \
64 v8::Handle<v8::String> symbol = v8::String::NewSymbol(#Name); \
65 if (symbol.IsEmpty()) \
66 return false; \
67 v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(v8::Local<v8::Context>::New(m_isolate, m_context)->Global()->Get(symbol)); \
68 if (object.IsEmpty()) \
69 return false; \
70 v8::Handle<v8::Value> prototypeValue = object->Get(prototypeString); \
71 if (prototypeValue.IsEmpty()) \
72 return false; \
73 m_##name##Prototype.set(m_isolate, prototypeValue); \
74 }
75
76 bool V8PerContextData::init()
77 {
78 v8::Handle<v8::Context> context = v8::Local<v8::Context>::New(m_isolate, m_context);
79 context->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, this);
80
81 v8::Handle<v8::String> prototypeString = v8::String::NewSymbol("prototype");
82 if (prototypeString.IsEmpty())
83 return false;
84
85 V8_STORE_PRIMORDIAL(error, Error);
86
87 return true;
88 }
90 #undef V8_STORE_PRIMORDIAL
dispose
49 void V8PerContextData::dispose()
50 {
51 v8::HandleScope handleScope(m_isolate);
52 v8::Local<v8::Context>::New(m_isolate, m_context)->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, 0);
53
54 disposeMapWithUnsafePersistentValues(&m_wrapperBoilerplates);
55 disposeMapWithUnsafePersistentValues(&m_constructorMap);
56 m_customElementBindings.clear();
57
58 m_context.Dispose(); // persist object to dispose.
59 }
DOMWrapperWorld
Class Define
This class represent a collection of DOM wrappers for a specific world.
49 class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
50 public:
51 static const int mainWorldId = 0;
52 static const int mainWorldExtensionGroup = 0;
53 static PassRefPtr<DOMWrapperWorld> ensureIsolatedWorld(int worldId, int extensionGroup);
54 ~DOMWrapperWorld();
55
56 static bool isolatedWorldsExist() { return isolatedWorldCount; }
57 static bool isIsolatedWorldId(int worldId) { return worldId > mainWorldId; }
58 static void getAllWorlds(Vector<RefPtr<DOMWrapperWorld> >& worlds);
59
60 void setIsolatedWorldField(v8::Handle<v8::Context>);
61
62 static DOMWrapperWorld* isolatedWorld(v8::Handle<v8::Context> context)
63 {
64 ASSERT(contextHasCorrectPrototype(context));
65 return static_cast<DOMWrapperWorld*>(context->GetAlignedPointerFromEmbedderData(v8ContextIsolatedWorld));
66 }
67 ........................................
108 private:
109 static int isolatedWorldCount;
110 static PassRefPtr<DOMWrapperWorld> createMainWorld();
111 static bool contextHasCorrectPrototype(v8::Handle<v8::Context>);
112
113 DOMWrapperWorld(int worldId, int extensionGroup);
114
115 const int m_worldId;
116 const int m_extensionGroup;
117 OwnPtr<DOMDataStore> m_domDataStore;
118
119 friend DOMWrapperWorld* mainThreadNormalWorld();
120 friend DOMWrapperWorld* existingWindowShellWorkaroundWorld();
121 };
122
123 DOMWrapperWorld* mainThreadNormalWorld();
mainThreadNormalWorld
55 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::createMainWorld()
56 {
57 return adoptRef(new DOMWrapperWorld(mainWorldId, mainWorldExtensionGroup));
58 }
59
60 DOMWrapperWorld::DOMWrapperWorld(int worldId, int extensionGroup)
61 : m_worldId(worldId)
62 , m_extensionGroup(extensionGroup)
63 {
64 if (isIsolatedWorld())
65 m_domDataStore = adoptPtr(new DOMDataStore(IsolatedWorld));
66 }
80 DOMWrapperWorld* mainThreadNormalWorld() // get static local main DOMWrapperWorld.
81 {
82 ASSERT(isMainThread());
83 DEFINE_STATIC_LOCAL(RefPtr<DOMWrapperWorld>, cachedNormalWorld, (DOMWrapperWorld::createMainWorld()));
84 return cachedNormalWorld.get();
85 }
ensureIsolatedWorld
107 typedef HashMap<int, DOMWrapperWorld*> WorldMap;
108 static WorldMap& isolatedWorldMap()
109 {
110 ASSERT(isMainThread());
111 DEFINE_STATIC_LOCAL(WorldMap, map, ());
112 return map;
113 }
143 PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld(int worldId, int extensionGroup)
144 {
145 ASSERT(worldId > mainWorldId);
146
147 WorldMap& map = isolatedWorldMap();
148 WorldMap::AddResult result = map.add(worldId, 0);
149 RefPtr<DOMWrapperWorld> world = result.iterator->value;
150 if (world) {
151 ASSERT(world->worldId() == worldId);
152 ASSERT(world->extensionGroup() == extensionGroup);
153 return world.release();
154 }
155
156 world = adoptRef(new DOMWrapperWorld(worldId, extensionGroup));
157 result.iterator->value = world.get();
158 isolatedWorldCount++;
159 ASSERT(map.size() == isolatedWorldCount); //int DOMWrapperWorld::isolatedWorldCount = 0; global value.
160
161 return world.release();
162 }
ScriptController
Class Define
72 class ScriptController {
73 public:
74 ScriptController(Frame*);
75 ~ScriptController();
76
77 bool initializeMainWorld();
78 V8WindowShell* windowShell(DOMWrapperWorld*);
79 V8WindowShell* existingWindowShell(DOMWrapperWorld*);
84 // Evaluate JavaScript in the main world.
85 ScriptValue executeScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin);
86
87 // Executes JavaScript in an isolated world. The script gets its own global scope,
88 // its own prototypes for intrinsic JavaScript objects (String, Array, and so-on),
89 // and its own wrappers for all DOM nodes and DOM constructors.
90 //
91 // If an isolated world with the specified ID already exists, it is reused.
92 // Otherwise, a new world is created.
93 //
94 // FIXME: Get rid of extensionGroup here.
95 void executeScriptInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup, Vector<ScriptValue>* results);
96
97 // Returns true if argument is a JavaScript URL.
98 bool executeScriptIfJavaScriptURL(const KURL&);
99
100 v8::Local<v8::Value> compileAndRunScript(const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin);
101
102 v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]);
103 ScriptValue callFunctionEvenIfScriptDisabled(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]);
104 static v8::Local<v8::Value> callFunctionWithInstrumentation(ScriptExecutionContext*, v8::Handle<v8::Function>, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> args[]);
105
111 // Creates a property of the global object of a frame.
112 void bindToWindowObject(Frame*, const String& key, NPObject*);
113 ...................................................
126 // Returns V8 Context. If none exists, creates a new context.
127 // It is potentially slow and consumes memory.
128 static v8::Local<v8::Context> mainWorldContext(Frame*);
129 v8::Local<v8::Context> mainWorldContext();
130 v8::Local<v8::Context> currentWorldContext();
141 void clearWindowShell();
142 void updateDocument();
147 void updateSecurityOrigin();
148 void clearScriptObjects();
149 void cleanupScriptObjectsForPlugin(Widget*);
150
151 void clearForClose();
152 void clearForOutOfMemory();
163 bool setContextDebugId(int);
164 static int contextDebugId(v8::Handle<v8::Context>);
165
166 private:
167 typedef HashMap<int, OwnPtr<V8WindowShell> > IsolatedWorldMap;
168 typedef HashMap<Widget*, NPObject*> PluginObjectMap;
169
170 void clearForClose(bool destroyGlobal);
171
172 Frame* m_frame;
173 const String* m_sourceURL;
174 v8::Isolate* m_isolate;
175
176 OwnPtr<V8WindowShell> m_windowShell; // has main windowShell
177 IsolatedWorldMap m_isolatedWorlds; // a map of V8WindowShell object for different worldID.
178
179 bool m_paused;
180 .........................................
188 };
Construct Function
90 ScriptController::ScriptController(Frame* frame)
91 : m_frame(frame)
92 , m_sourceURL(0)
93 , m_isolate(v8::Isolate::GetCurrent())
94 , m_windowShell(V8WindowShell::create(frame, mainThreadNormalWorld(), m_isolate)) // when ScriptController is created, it'll create its main V8WindowShell.
95 , m_paused(false)
96 , m_windowScriptNPObject(0)
97 {
98 }
windowShell
It’ll get or create a V8WindowShell for a DOMWrapperWorld.
66 V8WindowShell* ScriptController::windowShell(DOMWrapperWorld* world)
67 {
68 ASSERT(world);
69
70 V8WindowShell* shell = 0;
71 if (world->isMainWorld())
72 shell = m_windowShell.get();
73 else {
74 IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(world->worldId());
75 if (iter != m_isolatedWorlds.end())
76 shell = iter->value.get();
77 else {
78 OwnPtr<V8WindowShell> isolatedWorldShell = V8WindowShell::create(m_frame, world, m_isolate);// create V8WindowShell.
79 shell = isolatedWorldShell.get();
80 m_isolatedWorlds.set(world->worldId(), isolatedWorldShell.release());
81 }
82 }
83 if (!shell->isContextInitialized() && shell->initializeIfNeeded()) { // may create v8::Context.
84 if (world->isMainWorld()) {
85 // FIXME: Remove this if clause. See comment with existingWindowShellWorkaroundWorld().
86 m_frame->loader()->dispatchDidClearWindowObjectInWorld(existingWindowShellWorkaroundWorld());
87 } else
88 m_frame->loader()->dispatchDidClearWindowObjectInWorld(world);
89 }
90 return shell;
91 }
updateDocument
560 void ScriptController::updateDocument()
561 {
562 // For an uninitialized main window shell, do not incur the cost of context initialization during FrameLoader::init().
563 if ((!m_windowShell->isContextInitialized() || !m_windowShell->isGlobalInitialized()) && m_frame->loader()->stateMachine()->creatingInitialEmptyDocument())
564 return;
565
566 if (!initializeMainWorld())
567 windowShell(mainThreadNormalWorld())->updateDocument();
568 }
initializeMainWorld
242 bool ScriptController::initializeMainWorld()
243 {
244 if (m_windowShell->isContextInitialized())
245 return false;
246 return windowShell(mainThreadNormalWorld())->isContextInitialized();
247 }
clearForClose
130 void ScriptController::clearForClose(bool destroyGlobal)
131 {
132 m_windowShell->clearForClose(destroyGlobal);
133 for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); iter != m_isolatedWorlds.end(); ++iter)
134 iter->value->clearForClose(destroyGlobal);
135 V8GCController::hintForCollectGarbage();
136 }
138 void ScriptController::clearForClose()
139 {
140 double start = currentTime();
141 clearForClose(false);
142 HistogramSupport::histogramCustomCounts("WebCore.ScriptController.clearForClose", (currentTime() - start) * 1000, 0, 10000, 50);
143 }
Frame have ScriptController Object
Frame Class Define
70 class Frame : public RefCounted<Frame> {
71 public:
72 static PassRefPtr<Frame> create(Page*, HTMLFrameOwnerElement*, FrameLoaderClient*);
73
74 void init();
75 void setView(PassRefPtr<FrameView>);
76 void createView(const IntSize&, const StyleColor&, bool,
77 const IntSize& fixedLayoutSize = IntSize(), bool useFixedLayout = false, ScrollbarMode = ScrollbarAuto, bool horizontalLock = false,
78 ScrollbarMode = ScrollbarAuto, bool verticalLock = false);
79
80 ~Frame();
81
82 void addDestructionObserver(FrameDestructionObserver*);
.....................................................
222 inline ScriptController* Frame::script()
223 {
224 return m_script.get();
225 }
................................................
171 private:
172 Frame(Page*, HTMLFrameOwnerElement*, FrameLoaderClient*);
173
174 HashSet<FrameDestructionObserver*> m_destructionObservers;
175
176 Page* m_page;
177 mutable FrameTree m_treeNode;
178 mutable FrameLoader m_loader;
179 mutable NavigationScheduler m_navigationScheduler;
180
181 HTMLFrameOwnerElement* m_ownerElement;
182 RefPtr<FrameView> m_view;
183 RefPtr<DOMWindow> m_domWindow;
184
185 OwnPtr<ScriptController> m_script; // play here.
186 OwnPtr<Editor> m_editor;
187 OwnPtr<FrameSelection> m_selection;
188 OwnPtr<EventHandler> m_eventHandler;
189 OwnPtr<AnimationController> m_animationController;
190 OwnPtr<InputMethodController> m_inputMethodController;
191
192 float m_pageZoomFactor;
193 float m_textZoomFactor;
194
195 #if ENABLE(ORIENTATION_EVENTS)
196 int m_orientation;
197 #endif
198
199 bool m_inViewSourceMode;
200 };
Frame Construct
100 inline Frame::Frame(Page* page, HTMLFrameOwnerElement* ownerElement, FrameLoaderClient* frameLoaderClient)
101 : m_page(page)
102 , m_treeNode(this, parentFromOwnerElement(ownerElement))
103 , m_loader(this, frameLoaderClient)
104 , m_navigationScheduler(this)
105 , m_ownerElement(ownerElement)
106 , m_script(adoptPtr(new ScriptController(this))) // create ScriptController.
107 , m_editor(adoptPtr(new Editor(this)))
108 , m_selection(adoptPtr(new FrameSelection(this)))
109 , m_eventHandler(adoptPtr(new EventHandler(this)))
110 , m_animationController(adoptPtr(new AnimationController(this)))
111 , m_inputMethodController(InputMethodController::create(this))
112 , m_pageZoomFactor(parentPageZoomFactor(this))
113 , m_textZoomFactor(parentTextZoomFactor(this))
114 #if ENABLE(ORIENTATION_EVENTS)
115 , m_orientation(0)
116 #endif
117 , m_inViewSourceMode(false)
118 {
119 ASSERT(page);
120
121 if (ownerElement) {
122 page->incrementSubframeCount();
123 ownerElement->setContentFrame(this);
124 }
125
126 #ifndef NDEBUG
127 frameCounter.increment();
128 #endif
129 }
Who Call initializeMainWorld
ScriptController::updateDocument()=>ScriptController::initializeMainWorld()=>ScriptController::windowShell=>V8WindowShell::create and initializeIfNeeded.
DocumentLoader::createWriterFor
991 PassRefPtr<DocumentWriter> DocumentLoader::createWriterFor(Frame* frame, const Document* ownerDocument, const KURL& url, const String& mimeType, const String& encoding, bool userChosen, bool dispatch)
992 {
993 // Create a new document before clearing the frame, because it may need to
994 // inherit an aliased security context.
995 RefPtr<Document> document = DOMImplementation::createDocument(mimeType, frame, url, frame->inViewSourceMode());
996 if (document->isPluginDocument() && document->isSandboxed(SandboxPlugins))
997 document = SinkDocument::create(DocumentInit(url, frame));
998 bool shouldReuseDefaultView = frame->loader()->stateMachine()->isDisplayingInitialEmptyDocument() && frame->document()->isSecureTransitionTo(url);
999
1000 ClearOptions options = 0;
1001 if (!shouldReuseDefaultView)
1002 options = ClearWindowProperties | ClearScriptObjects;
1003 frame->loader()->clear(options);
1004
1005 if (frame->document() && frame->document()->attached())
1006 frame->document()->prepareForDestruction();
1007
1008 if (!shouldReuseDefaultView)
1009 frame->setDOMWindow(DOMWindow::create(frame)); // it'll create DOMWindow
1010
1011 frame->loader()->setOutgoingReferrer(url);
1012 frame->domWindow()->setDocument(document); // call to DOMWindow's setDocument
1013
1014 if (ownerDocument) {
1015 document->setCookieURL(ownerDocument->cookieURL());
1016 document->setSecurityOrigin(ownerDocument->securityOrigin());
1017 }
1018
1019 frame->loader()->didBeginDocument(dispatch);
1020
1021 return DocumentWriter::create(document.get(), mimeType, encoding, userChosen);
1022 }
DOMWindow::setDocument
325 void DOMWindow::setDocument(PassRefPtr<Document> document)
326 {
327 ASSERT(!document || document->frame() == m_frame);
328 if (m_document) {
329 if (m_document->attached()) {
330 // FIXME: We don't call willRemove here. Why is that OK?
331 // This detach() call is also mostly redundant. Most of the calls to
332 // this function come via DocumentLoader::createWriterFor, which
333 // always detaches the previous Document first. Only XSLTProcessor
334 // depends on this detach() call, so it seems like there's some room
335 // for cleanup.
336 m_document->detach();
337 }
338 m_document->setDOMWindow(0);
339 }
340
341 m_document = document;
342
343 if (!m_document)
344 return;
345
346 m_document->setDOMWindow(this);
347 if (!m_document->attached())
348 m_document->attach();
349
350 if (!m_frame)
351 return;
352
353 m_frame->script()->updateDocument(); // it's important for its time to ScriptController's V8WindowShell.
354 m_document->updateViewportArguments();
355
356 if (m_frame->page() && m_frame->view()) {
357 if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator()) {
358 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_frame->view(), HorizontalScrollbar);
359 scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_frame->view(), VerticalScrollbar);
360 scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_frame->view());
361 }
362 }
363
364 m_frame->selection()->updateSecureKeyboardEntryIfActive();
365
366 if (m_frame->page() && m_frame->page()->mainFrame() == m_frame) {
367 m_frame->page()->mainFrame()->notifyChromeClientWheelEventHandlerCountChanged();
368 if (m_document->hasTouchEventHandlers())
369 m_frame->page()->chrome().client()->needTouchEvents(true);
370 }
371 }
##How about V8Window&&V8Window::info See Next.