Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/WindowProxy.cpp

Issue 1858613002: bindings: Makes the window object be the inner global object. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 ScriptState::Scope scope(m_scriptState.get()); 238 ScriptState::Scope scope(m_scriptState.get());
239 v8::Local<v8::Context> context = m_scriptState->context(); 239 v8::Local<v8::Context> context = m_scriptState->context();
240 if (m_global.isEmpty()) { 240 if (m_global.isEmpty()) {
241 m_global.set(m_isolate, context->Global()); 241 m_global.set(m_isolate, context->Global());
242 if (m_global.isEmpty()) { 242 if (m_global.isEmpty()) {
243 disposeContext(DoNotDetachGlobal); 243 disposeContext(DoNotDetachGlobal);
244 return false; 244 return false;
245 } 245 }
246 } 246 }
247 247
248 if (!installDOMWindow()) { 248 if (!setupWindowPrototypeChain()) {
249 disposeContext(DoNotDetachGlobal); 249 disposeContext(DoNotDetachGlobal);
250 return false; 250 return false;
251 } 251 }
252 252
253 SecurityOrigin* origin = 0; 253 SecurityOrigin* origin = 0;
254 if (m_world->isMainWorld()) { 254 if (m_world->isMainWorld()) {
255 // ActivityLogger for main world is updated within updateDocument(). 255 // ActivityLogger for main world is updated within updateDocument().
256 updateDocument(); 256 updateDocument();
257 origin = m_frame->securityContext()->getSecurityOrigin(); 257 origin = m_frame->securityContext()->getSecurityOrigin();
258 // FIXME: Can this be removed when CSP moves to browser? 258 // FIXME: Can this be removed when CSP moves to browser?
259 ContentSecurityPolicy* csp = m_frame->securityContext()->contentSecurity Policy(); 259 ContentSecurityPolicy* csp = m_frame->securityContext()->contentSecurity Policy();
260 context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurit yPolicy::SuppressReport)); 260 context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurit yPolicy::SuppressReport));
261 context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage())); 261 context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage()));
262 } else { 262 } else {
263 updateActivityLogger(); 263 updateActivityLogger();
264 origin = m_world->isolatedWorldSecurityOrigin(); 264 origin = m_world->isolatedWorldSecurityOrigin();
265 setSecurityToken(origin); 265 setSecurityToken(origin);
266 } 266 }
267 if (m_frame->isLocalFrame()) { 267 if (m_frame->isLocalFrame()) {
268 LocalFrame* frame = toLocalFrame(m_frame); 268 LocalFrame* frame = toLocalFrame(m_frame);
269 MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), fram e, origin); 269 MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), fram e, origin);
270 frame->loader().client()->didCreateScriptContext(context, m_world->exten sionGroup(), m_world->worldId()); 270 frame->loader().client()->didCreateScriptContext(context, m_world->exten sionGroup(), m_world->worldId());
271 } 271 }
272 return true; 272 return true;
273 } 273 }
274 274
275 namespace {
276
277 void configureInnerGlobalObjectTemplate(v8::Local<v8::ObjectTemplate> templ, v8: :Isolate* isolate)
278 {
279 // Install a security handler with V8.
280 templ->SetAccessCheckCallback(V8Window::securityCheckCustom, v8::External::N ew(isolate, const_cast<WrapperTypeInfo*>(&V8Window::wrapperTypeInfo)));
281 templ->SetInternalFieldCount(V8Window::internalFieldCount);
282 }
283
284 v8::Local<v8::ObjectTemplate> getInnerGlobalObjectTemplate(v8::Isolate* isolate)
285 {
286 // It is OK to share the same object template between the main world and
287 // non-main worlds because the inner global object doesn't install any
288 // DOM attributes/methods.
289 DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, innerGlobalObjectTem plate, ());
290 if (innerGlobalObjectTemplate.IsEmpty()) {
291 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "BuildDOMTemplate");
292 v8::Local<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate);
293 configureInnerGlobalObjectTemplate(templ, isolate);
294 innerGlobalObjectTemplate.Reset(isolate, templ);
295 }
296 return v8::Local<v8::ObjectTemplate>::New(isolate, innerGlobalObjectTemplate );
297 }
298
299 } // namespace
300
301 void WindowProxy::createContext() 275 void WindowProxy::createContext()
302 { 276 {
303 // FIXME: This should be a null check of m_frame->client(), but there are st ill some edge cases 277 // FIXME: This should be a null check of m_frame->client(), but there are st ill some edge cases
304 // that this fails to catch during frame detach. 278 // that this fails to catch during frame detach.
305 if (m_frame->isLocalFrame() && !toLocalFrame(m_frame)->loader().documentLoad er()) 279 if (m_frame->isLocalFrame() && !toLocalFrame(m_frame)->loader().documentLoad er())
306 return; 280 return;
307 281
308 // Create a new environment using an empty template for the shadow 282 // Create a new v8::Context with the window object as the global object
309 // object. Reuse the global object if one has been created earlier. 283 // (aka the inner global). Reuse the global proxy object (aka the outer
310 v8::Local<v8::ObjectTemplate> globalTemplate = getInnerGlobalObjectTemplate( m_isolate); 284 // global) if it already exists. See the comments in
285 // setupWindowPrototypeChain for the structure of the prototype chain of
286 // the global object.
287 v8::Local<v8::ObjectTemplate> globalTemplate = V8Window::domTemplate(m_isola te, *m_world)->InstanceTemplate();
311 if (globalTemplate.IsEmpty()) 288 if (globalTemplate.IsEmpty())
312 return; 289 return;
313 290
314 // FIXME: It's not clear what the right thing to do for remote frames is. 291 // FIXME: It's not clear what the right thing to do for remote frames is.
315 // The extensions registered don't generally seem to make sense for remote 292 // The extensions registered don't generally seem to make sense for remote
316 // frames, so skip it for now. 293 // frames, so skip it for now.
317 Vector<const char*> extensionNames; 294 Vector<const char*> extensionNames;
318 if (m_frame->isLocalFrame()) { 295 if (m_frame->isLocalFrame()) {
319 LocalFrame* frame = toLocalFrame(m_frame); 296 LocalFrame* frame = toLocalFrame(m_frame);
320 // Dynamically tell v8 about our extensions now. 297 // Dynamically tell v8 about our extensions now.
321 const V8Extensions& extensions = ScriptController::registeredExtensions( ); 298 const V8Extensions& extensions = ScriptController::registeredExtensions( );
322 extensionNames.reserveInitialCapacity(extensions.size()); 299 extensionNames.reserveInitialCapacity(extensions.size());
323 int extensionGroup = m_world->extensionGroup(); 300 int extensionGroup = m_world->extensionGroup();
324 int worldId = m_world->worldId(); 301 int worldId = m_world->worldId();
325 for (const auto* extension : extensions) { 302 for (const auto* extension : extensions) {
326 if (!frame->loader().client()->allowScriptExtension(extension->name( ), extensionGroup, worldId)) 303 if (!frame->loader().client()->allowScriptExtension(extension->name( ), extensionGroup, worldId))
327 continue; 304 continue;
328 305
329 extensionNames.append(extension->name()); 306 extensionNames.append(extension->name());
330 } 307 }
331 } 308 }
332 v8::ExtensionConfiguration extensionConfiguration(extensionNames.size(), ext ensionNames.data()); 309 v8::ExtensionConfiguration extensionConfiguration(extensionNames.size(), ext ensionNames.data());
333 310
334 v8::Local<v8::Context> context = v8::Context::New(m_isolate, &extensionConfi guration, globalTemplate, m_global.newLocal(m_isolate)); 311 v8::Local<v8::Context> context;
312 {
313 V8PerIsolateData::UseCounterDisabledScope useCounterDisabled(V8PerIsolat eData::from(m_isolate));
314 context = v8::Context::New(m_isolate, &extensionConfiguration, globalTem plate, m_global.newLocal(m_isolate));
315 }
335 if (context.IsEmpty()) 316 if (context.IsEmpty())
336 return; 317 return;
337 m_scriptState = ScriptState::create(context, m_world); 318 m_scriptState = ScriptState::create(context, m_world);
338 } 319 }
339 320
340 static v8::Local<v8::Object> toInnerGlobalObject(v8::Local<v8::Context> context) 321 bool WindowProxy::setupWindowPrototypeChain()
341 { 322 {
342 return v8::Local<v8::Object>::Cast(context->Global()->GetPrototype()); 323 // Associate the window wrapper object and its prototype chain with the
343 } 324 // corresponding native DOMWindow object.
325 // The full structure of the global object's prototype chain is as follows:
326 //
327 // global proxy object [1]
328 // -- has prototype --> global object (window wrapper object) [2]
haraken 2016/04/18 08:04:15 I'd rename: - "global proxy object" => "outer glo
329 // -- has prototype --> Window.prototype
330 // -- has prototype --> WindowProperties [3]
331 // -- has prototype --> EventTarget.prototype
332 // -- has prototype --> Object.prototype
333 // -- has prototype --> null
334 //
335 // [1] Global proxy object is as known as "outer global object". It's an
336 // empty object and remains after navigation. When navigated, points to
337 // a different global object as the prototype object.
338 // [2] Global object is as known as "inner global object" or "window wrapper
339 // object". The prototype chain between global proxy object and global
340 // object is NOT observable from user JavaScript code. All other
341 // prototype chains are observable. Global proxy object and global object
342 // together appear to be the same single JavaScript object. See also:
343 // https://wiki.mozilla.org/Gecko:SplitWindow
344 // global object (= window wrapper object) provides most of Window's DOM
345 // attributes and operations. Also global variables defined by user
346 // JavaScript are placed on this object. When navigated, a new global
347 // object is created together with a new v8::Context, but the global proxy
348 // object doesn't change.
349 // [3] WindowProperties is a named properties object of Window interface.
344 350
345 bool WindowProxy::installDOMWindow()
346 {
347 DOMWindow* window = m_frame->domWindow(); 351 DOMWindow* window = m_frame->domWindow();
348 const WrapperTypeInfo* wrapperTypeInfo = window->wrapperTypeInfo(); 352 const WrapperTypeInfo* wrapperTypeInfo = window->wrapperTypeInfo();
349 v8::Local<v8::Object> windowWrapper; 353
350 v8::Local<v8::Function> constructor = m_scriptState->perContextData()->const ructorForType(wrapperTypeInfo); 354 v8::Local<v8::Context> context = m_scriptState->context();
351 if (constructor.IsEmpty()) 355 // The global proxy object. Note this is not the global object.
352 return false; 356 v8::Local<v8::Object> globalProxy = context->Global();
353 if (!V8ObjectConstructor::newInstance(m_isolate, constructor).ToLocal(&windo wWrapper)) 357 // The global object, aka window wrapper object.
354 return false; 358 v8::Local<v8::Object> windowWrapper = globalProxy->GetPrototype().As<v8::Obj ect>();
355 windowWrapper = V8DOMWrapper::associateObjectWithWrapper(m_isolate, window, wrapperTypeInfo, windowWrapper); 359 windowWrapper = V8DOMWrapper::associateObjectWithWrapper(m_isolate, window, wrapperTypeInfo, windowWrapper);
356 360 // The prototype object of Window interface.
357 v8::Local<v8::Object> windowPrototype = v8::Local<v8::Object>::Cast(windowWr apper->GetPrototype()); 361 v8::Local<v8::Object> windowPrototype = windowWrapper->GetPrototype().As<v8: :Object>();
358 RELEASE_ASSERT(!windowPrototype.IsEmpty()); 362 RELEASE_ASSERT(!windowPrototype.IsEmpty());
359 V8DOMWrapper::setNativeInfo(windowPrototype, wrapperTypeInfo, window); 363 V8DOMWrapper::setNativeInfo(windowPrototype, wrapperTypeInfo, window);
haraken 2016/04/18 08:04:15 Not directly related to this CL, do you know why w
Yuki 2016/04/18 08:27:07 Not sure. I vaguely guess that we can remove it.
360 v8::Local<v8::Object> windowProperties = v8::Local<v8::Object>::Cast(windowP rototype->GetPrototype()); 364 // The named properties object of Window interface.
365 v8::Local<v8::Object> windowProperties = windowPrototype->GetPrototype().As< v8::Object>();
361 RELEASE_ASSERT(!windowProperties.IsEmpty()); 366 RELEASE_ASSERT(!windowProperties.IsEmpty());
362 V8DOMWrapper::setNativeInfo(windowProperties, wrapperTypeInfo, window); 367 V8DOMWrapper::setNativeInfo(windowProperties, wrapperTypeInfo, window);
haraken 2016/04/18 08:04:15 Ditto.
363 368
364 // Install the windowWrapper as the prototype of the innerGlobalObject.
365 // The full structure of the global object is as follows:
366 //
367 // outerGlobalObject (Empty object, remains after navigation)
368 // -- has prototype --> innerGlobalObject (Holds global variables, changes during navigation)
369 // -- has prototype --> DOMWindow instance
370 // -- has prototype --> Window.prototype
371 // -- has prototype --> WindowProperties (named properties object)
372 // -- has prototype --> EventTarget.prototype
373 // -- has prototype --> Object.prototype
374 //
375 // Note: Much of this prototype structure is hidden from web content. The
376 // outer, inner, and DOMWindow instance all appear to be the same
377 // JavaScript object.
378 v8::Local<v8::Context> context = m_scriptState->context();
379 v8::Local<v8::Object> innerGlobalObject = toInnerGlobalObject(m_scriptState- >context());
380 V8DOMWrapper::setNativeInfo(innerGlobalObject, wrapperTypeInfo, window);
381 if (!v8CallBoolean(innerGlobalObject->SetPrototype(context, windowWrapper)))
382 return false;
383
384 // TODO(keishi): Remove installPagePopupController and implement 369 // TODO(keishi): Remove installPagePopupController and implement
385 // PagePopupController in another way. 370 // PagePopupController in another way.
386 V8PagePopupControllerBinding::installPagePopupController(context, windowWrap per); 371 V8PagePopupControllerBinding::installPagePopupController(context, windowWrap per);
387 return true; 372 return true;
388 } 373 }
389 374
390 void WindowProxy::updateDocumentWrapper(v8::Local<v8::Object> wrapper) 375 void WindowProxy::updateDocumentWrapper(v8::Local<v8::Object> wrapper)
391 { 376 {
392 ASSERT(m_world->isMainWorld()); 377 ASSERT(m_world->isMainWorld());
393 m_document.set(m_isolate, wrapper); 378 m_document.set(m_isolate, wrapper);
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
560 } 545 }
561 546
562 void WindowProxy::updateSecurityOrigin(SecurityOrigin* origin) 547 void WindowProxy::updateSecurityOrigin(SecurityOrigin* origin)
563 { 548 {
564 if (!isContextInitialized()) 549 if (!isContextInitialized())
565 return; 550 return;
566 setSecurityToken(origin); 551 setSecurityToken(origin);
567 } 552 }
568 553
569 } // namespace blink 554 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698