| 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/ConditionalFeatures.h" | |
| 34 #include "bindings/core/v8/DOMWrapperWorld.h" | |
| 35 #include "bindings/core/v8/ScriptController.h" | |
| 36 #include "bindings/core/v8/ToV8.h" | |
| 37 #include "bindings/core/v8/V8Binding.h" | 33 #include "bindings/core/v8/V8Binding.h" |
| 38 #include "bindings/core/v8/V8DOMActivityLogger.h" | 34 #include "bindings/core/v8/V8DOMWrapper.h" |
| 39 #include "bindings/core/v8/V8Document.h" | |
| 40 #include "bindings/core/v8/V8GCForContextDispose.h" | 35 #include "bindings/core/v8/V8GCForContextDispose.h" |
| 41 #include "bindings/core/v8/V8HTMLCollection.h" | |
| 42 #include "bindings/core/v8/V8HTMLDocument.h" | |
| 43 #include "bindings/core/v8/V8HiddenValue.h" | |
| 44 #include "bindings/core/v8/V8Initializer.h" | |
| 45 #include "bindings/core/v8/V8ObjectConstructor.h" | |
| 46 #include "bindings/core/v8/V8PagePopupControllerBinding.h" | 36 #include "bindings/core/v8/V8PagePopupControllerBinding.h" |
| 47 #include "bindings/core/v8/V8PrivateProperty.h" | 37 #include "core/frame/DOMWindow.h" |
| 48 #include "bindings/core/v8/V8Window.h" | 38 #include "core/frame/Frame.h" |
| 49 #include "core/frame/LocalFrame.h" | |
| 50 #include "core/frame/csp/ContentSecurityPolicy.h" | |
| 51 #include "core/html/DocumentNameCollection.h" | |
| 52 #include "core/html/HTMLCollection.h" | |
| 53 #include "core/html/HTMLIFrameElement.h" | |
| 54 #include "core/inspector/InspectorInstrumentation.h" | |
| 55 #include "core/inspector/MainThreadDebugger.h" | |
| 56 #include "core/loader/DocumentLoader.h" | |
| 57 #include "core/loader/FrameLoader.h" | |
| 58 #include "core/loader/FrameLoaderClient.h" | |
| 59 #include "core/origin_trials/OriginTrialContext.h" | |
| 60 #include "platform/Histogram.h" | |
| 61 #include "platform/RuntimeEnabledFeatures.h" | |
| 62 #include "platform/ScriptForbiddenScope.h" | |
| 63 #include "platform/heap/Handle.h" | |
| 64 #include "platform/instrumentation/tracing/TraceEvent.h" | |
| 65 #include "platform/weborigin/SecurityOrigin.h" | |
| 66 #include "public/platform/Platform.h" | |
| 67 #include "wtf/Assertions.h" | 39 #include "wtf/Assertions.h" |
| 68 #include "wtf/StringExtras.h" | |
| 69 #include "wtf/text/CString.h" | |
| 70 #include <algorithm> | |
| 71 #include <utility> | 40 #include <utility> |
| 72 #include <v8-debug.h> | |
| 73 #include <v8.h> | 41 #include <v8.h> |
| 74 | 42 |
| 75 namespace blink { | 43 namespace blink { |
| 76 | 44 |
| 77 WindowProxy* WindowProxy::create(v8::Isolate* isolate, | |
| 78 Frame* frame, | |
| 79 DOMWrapperWorld& world) { | |
| 80 return new WindowProxy(frame, &world, isolate); | |
| 81 } | |
| 82 | |
| 83 WindowProxy::WindowProxy(Frame* frame, | |
| 84 PassRefPtr<DOMWrapperWorld> world, | |
| 85 v8::Isolate* isolate) | |
| 86 : m_frame(frame), | |
| 87 m_isolate(isolate), | |
| 88 m_world(world), | |
| 89 m_lifecycle(Lifecycle::ContextUninitialized) {} | |
| 90 | |
| 91 WindowProxy::~WindowProxy() { | 45 WindowProxy::~WindowProxy() { |
| 92 // clearForClose() or clearForNavigation() must be invoked before destruction | 46 // clearForClose() or clearForNavigation() must be invoked before destruction |
| 93 // starts. | 47 // starts. |
| 94 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); | 48 DCHECK(m_lifecycle != Lifecycle::ContextInitialized); |
| 95 } | 49 } |
| 96 | 50 |
| 97 DEFINE_TRACE(WindowProxy) { | 51 DEFINE_TRACE(WindowProxy) { |
| 98 visitor->trace(m_frame); | 52 visitor->trace(m_frame); |
| 99 } | 53 } |
| 100 | 54 |
| 55 WindowProxy::WindowProxy(Frame& frame, |
| 56 v8::Isolate* isolate, |
| 57 RefPtr<DOMWrapperWorld> world) |
| 58 : m_frame(frame), |
| 59 m_isolate(isolate), |
| 60 m_world(std::move(world)), |
| 61 m_lifecycle(Lifecycle::ContextUninitialized) {} |
| 62 |
| 101 void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior) { | 63 void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior) { |
| 102 if (m_lifecycle != Lifecycle::ContextInitialized) | 64 DCHECK(m_lifecycle == Lifecycle::ContextInitialized); |
| 103 return; | |
| 104 | |
| 105 ScriptState::Scope scope(m_scriptState.get()); | |
| 106 v8::Local<v8::Context> context = m_scriptState->context(); | |
| 107 if (m_frame->isLocalFrame()) { | |
| 108 LocalFrame* frame = toLocalFrame(m_frame); | |
| 109 // The embedder could run arbitrary code in response to the | |
| 110 // willReleaseScriptContext callback, so all disposing should happen after | |
| 111 // it returns. | |
| 112 frame->loader().client()->willReleaseScriptContext(context, | |
| 113 m_world->worldId()); | |
| 114 MainThreadDebugger::instance()->contextWillBeDestroyed(m_scriptState.get()); | |
| 115 } | |
| 116 | 65 |
| 117 if (behavior == DetachGlobal) { | 66 if (behavior == DetachGlobal) { |
| 67 v8::Local<v8::Context> context = m_scriptState->context(); |
| 118 // Clean up state on the global proxy, which will be reused. | 68 // Clean up state on the global proxy, which will be reused. |
| 119 if (!m_globalProxy.isEmpty()) { | 69 if (!m_globalProxy.isEmpty()) { |
| 120 // TODO(yukishiino): This DCHECK failed on Canary (M57) and Dev (M56). | 70 // TODO(yukishiino): This DCHECK failed on Canary (M57) and Dev (M56). |
| 121 // We need to figure out why m_globalProxy != context->Global(). | 71 // We need to figure out why m_globalProxy != context->Global(). |
| 122 DCHECK(m_globalProxy == context->Global()); | 72 DCHECK(m_globalProxy == context->Global()); |
| 123 DCHECK_EQ(toScriptWrappable(context->Global()), | 73 DCHECK_EQ(toScriptWrappable(context->Global()), |
| 124 toScriptWrappable( | 74 toScriptWrappable( |
| 125 context->Global()->GetPrototype().As<v8::Object>())); | 75 context->Global()->GetPrototype().As<v8::Object>())); |
| 126 m_globalProxy.get().SetWrapperClassId(0); | 76 m_globalProxy.get().SetWrapperClassId(0); |
| 127 } | 77 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 // When a frame navigates to a new page, the inner window is cut off | 165 // When a frame navigates to a new page, the inner window is cut off |
| 216 // the outer window, and the outer window identify is preserved for | 166 // the outer window, and the outer window identify is preserved for |
| 217 // the frame. However, a new inner window is created for the new page. | 167 // the frame. However, a new inner window is created for the new page. |
| 218 // If there are JS code holds a closure to the old inner window, | 168 // If there are JS code holds a closure to the old inner window, |
| 219 // it won't be able to reach the outer window via its global object. | 169 // it won't be able to reach the outer window via its global object. |
| 220 void WindowProxy::initializeIfNeeded() { | 170 void WindowProxy::initializeIfNeeded() { |
| 221 // TODO(haraken): It is wrong to re-initialize an already detached window | 171 // TODO(haraken): It is wrong to re-initialize an already detached window |
| 222 // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'. | 172 // proxy. This must be 'if(m_lifecycle == Lifecycle::ContextUninitialized)'. |
| 223 if (m_lifecycle != Lifecycle::ContextInitialized) { | 173 if (m_lifecycle != Lifecycle::ContextInitialized) { |
| 224 initialize(); | 174 initialize(); |
| 225 if (m_world->isMainWorld() && m_frame->isLocalFrame()) | |
| 226 toLocalFrame(m_frame)->loader().dispatchDidClearWindowObjectInMainWorld(); | |
| 227 } | 175 } |
| 228 } | 176 } |
| 229 | 177 |
| 230 void WindowProxy::initialize() { | |
| 231 TRACE_EVENT1("v8", "WindowProxy::initialize", "isMainWindow", | |
| 232 m_frame->isMainFrame()); | |
| 233 SCOPED_BLINK_UMA_HISTOGRAM_TIMER( | |
| 234 m_frame->isMainFrame() ? "Blink.Binding.InitializeMainWindowProxy" | |
| 235 : "Blink.Binding.InitializeNonMainWindowProxy"); | |
| 236 | |
| 237 ScriptForbiddenScope::AllowUserAgentScript allowScript; | |
| 238 | |
| 239 v8::HandleScope handleScope(m_isolate); | |
| 240 | |
| 241 createContext(); | |
| 242 | |
| 243 ScriptState::Scope scope(m_scriptState.get()); | |
| 244 v8::Local<v8::Context> context = m_scriptState->context(); | |
| 245 if (m_globalProxy.isEmpty()) { | |
| 246 m_globalProxy.set(m_isolate, context->Global()); | |
| 247 CHECK(!m_globalProxy.isEmpty()); | |
| 248 } | |
| 249 | |
| 250 setupWindowPrototypeChain(); | |
| 251 | |
| 252 SecurityOrigin* origin = 0; | |
| 253 if (m_world->isMainWorld()) { | |
| 254 // ActivityLogger for main world is updated within updateDocument(). | |
| 255 updateDocument(); | |
| 256 origin = m_frame->securityContext()->getSecurityOrigin(); | |
| 257 // FIXME: Can this be removed when CSP moves to browser? | |
| 258 ContentSecurityPolicy* csp = | |
| 259 m_frame->securityContext()->contentSecurityPolicy(); | |
| 260 context->AllowCodeGenerationFromStrings( | |
| 261 csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); | |
| 262 context->SetErrorMessageForCodeGenerationFromStrings( | |
| 263 v8String(m_isolate, csp->evalDisabledErrorMessage())); | |
| 264 } else { | |
| 265 updateActivityLogger(); | |
| 266 origin = m_world->isolatedWorldSecurityOrigin(); | |
| 267 setSecurityToken(origin); | |
| 268 } | |
| 269 | |
| 270 if (m_frame->isLocalFrame()) { | |
| 271 LocalFrame* frame = toLocalFrame(m_frame); | |
| 272 MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), frame, | |
| 273 origin); | |
| 274 frame->loader().client()->didCreateScriptContext( | |
| 275 context, m_world->extensionGroup(), m_world->worldId()); | |
| 276 } | |
| 277 // If conditional features for window have been queued before the V8 context | |
| 278 // was ready, then inject them into the context now | |
| 279 if (m_world->isMainWorld()) { | |
| 280 installPendingConditionalFeaturesOnWindow(m_scriptState.get()); | |
| 281 } | |
| 282 } | |
| 283 | |
| 284 void WindowProxy::createContext() { | |
| 285 // Create a new v8::Context with the window object as the global object | |
| 286 // (aka the inner global). Reuse the global proxy object (aka the outer | |
| 287 // global) if it already exists. See the comments in | |
| 288 // setupWindowPrototypeChain for the structure of the prototype chain of | |
| 289 // the global object. | |
| 290 v8::Local<v8::ObjectTemplate> globalTemplate = | |
| 291 V8Window::domTemplate(m_isolate, *m_world)->InstanceTemplate(); | |
| 292 CHECK(!globalTemplate.IsEmpty()); | |
| 293 | |
| 294 // FIXME: It's not clear what the right thing to do for remote frames is. | |
| 295 // The extensions registered don't generally seem to make sense for remote | |
| 296 // frames, so skip it for now. | |
| 297 Vector<const char*> extensionNames; | |
| 298 if (m_frame->isLocalFrame()) { | |
| 299 LocalFrame* frame = toLocalFrame(m_frame); | |
| 300 // Dynamically tell v8 about our extensions now. | |
| 301 const V8Extensions& extensions = ScriptController::registeredExtensions(); | |
| 302 extensionNames.reserveInitialCapacity(extensions.size()); | |
| 303 int extensionGroup = m_world->extensionGroup(); | |
| 304 int worldId = m_world->worldId(); | |
| 305 for (const auto* extension : extensions) { | |
| 306 if (!frame->loader().client()->allowScriptExtension( | |
| 307 extension->name(), extensionGroup, worldId)) | |
| 308 continue; | |
| 309 | |
| 310 extensionNames.push_back(extension->name()); | |
| 311 } | |
| 312 } | |
| 313 v8::ExtensionConfiguration extensionConfiguration(extensionNames.size(), | |
| 314 extensionNames.data()); | |
| 315 | |
| 316 v8::Local<v8::Context> context; | |
| 317 { | |
| 318 V8PerIsolateData::UseCounterDisabledScope useCounterDisabled( | |
| 319 V8PerIsolateData::from(m_isolate)); | |
| 320 context = | |
| 321 v8::Context::New(m_isolate, &extensionConfiguration, globalTemplate, | |
| 322 m_globalProxy.newLocal(m_isolate)); | |
| 323 } | |
| 324 CHECK(!context.IsEmpty()); | |
| 325 | |
| 326 m_scriptState = ScriptState::create(context, m_world); | |
| 327 | |
| 328 // TODO(haraken): Currently we cannot enable the following DCHECK because | |
| 329 // an already detached window proxy can be re-initialized. This is wrong. | |
| 330 // DCHECK(m_lifecycle == Lifecycle::ContextUninitialized); | |
| 331 m_lifecycle = Lifecycle::ContextInitialized; | |
| 332 DCHECK(m_scriptState->contextIsValid()); | |
| 333 } | |
| 334 | |
| 335 void WindowProxy::setupWindowPrototypeChain() { | 178 void WindowProxy::setupWindowPrototypeChain() { |
| 336 // Associate the window wrapper object and its prototype chain with the | 179 // Associate the window wrapper object and its prototype chain with the |
| 337 // corresponding native DOMWindow object. | 180 // corresponding native DOMWindow object. |
| 338 // The full structure of the global object's prototype chain is as follows: | 181 // The full structure of the global object's prototype chain is as follows: |
| 339 // | 182 // |
| 340 // global proxy object [1] | 183 // global proxy object [1] |
| 341 // -- has prototype --> global object (window wrapper object) [2] | 184 // -- has prototype --> global object (window wrapper object) [2] |
| 342 // -- has prototype --> Window.prototype | 185 // -- has prototype --> Window.prototype |
| 343 // -- has prototype --> WindowProperties [3] | 186 // -- has prototype --> WindowProperties [3] |
| 344 // -- has prototype --> EventTarget.prototype | 187 // -- has prototype --> EventTarget.prototype |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 CHECK(!windowProperties.IsEmpty()); | 235 CHECK(!windowProperties.IsEmpty()); |
| 393 V8DOMWrapper::setNativeInfo(m_isolate, windowProperties, wrapperTypeInfo, | 236 V8DOMWrapper::setNativeInfo(m_isolate, windowProperties, wrapperTypeInfo, |
| 394 window); | 237 window); |
| 395 | 238 |
| 396 // TODO(keishi): Remove installPagePopupController and implement | 239 // TODO(keishi): Remove installPagePopupController and implement |
| 397 // PagePopupController in another way. | 240 // PagePopupController in another way. |
| 398 V8PagePopupControllerBinding::installPagePopupController(context, | 241 V8PagePopupControllerBinding::installPagePopupController(context, |
| 399 windowWrapper); | 242 windowWrapper); |
| 400 } | 243 } |
| 401 | 244 |
| 402 void WindowProxy::updateDocumentProperty() { | |
| 403 DCHECK(m_world->isMainWorld()); | |
| 404 | |
| 405 if (m_frame->isRemoteFrame()) | |
| 406 return; | |
| 407 | |
| 408 ScriptState::Scope scope(m_scriptState.get()); | |
| 409 v8::Local<v8::Context> context = m_scriptState->context(); | |
| 410 LocalFrame* frame = toLocalFrame(m_frame); | |
| 411 v8::Local<v8::Value> documentWrapper = | |
| 412 ToV8(frame->document(), context->Global(), m_isolate); | |
| 413 DCHECK(documentWrapper->IsObject()); | |
| 414 // Update the cached accessor for window.document. | |
| 415 CHECK(V8PrivateProperty::getWindowDocumentCachedAccessor(m_isolate).set( | |
| 416 context, context->Global(), documentWrapper)); | |
| 417 } | |
| 418 | |
| 419 void WindowProxy::updateActivityLogger() { | |
| 420 m_scriptState->perContextData()->setActivityLogger( | |
| 421 V8DOMActivityLogger::activityLogger( | |
| 422 m_world->worldId(), | |
| 423 m_frame->isLocalFrame() && toLocalFrame(m_frame)->document() | |
| 424 ? toLocalFrame(m_frame)->document()->baseURI() | |
| 425 : KURL())); | |
| 426 } | |
| 427 | |
| 428 void WindowProxy::setSecurityToken(SecurityOrigin* origin) { | |
| 429 // If two tokens are equal, then the SecurityOrigins canAccess each other. | |
| 430 // If two tokens are not equal, then we have to call canAccess. | |
| 431 // Note: we can't use the HTTPOrigin if it was set from the DOM. | |
| 432 String token; | |
| 433 // There are two situations where v8 needs to do a full canAccess check, | |
| 434 // so set an empty security token instead: | |
| 435 // - document.domain was modified | |
| 436 // - the frame is remote | |
| 437 bool delaySet = m_frame->isRemoteFrame() || | |
| 438 (m_world->isMainWorld() && origin->domainWasSetInDOM()); | |
| 439 if (origin && !delaySet) | |
| 440 token = origin->toString(); | |
| 441 | |
| 442 // An empty or "null" token means we always have to call | |
| 443 // canAccess. The toString method on securityOrigins returns the | |
| 444 // string "null" for empty security origins and for security | |
| 445 // origins that should only allow access to themselves. In this | |
| 446 // case, we use the global object as the security token to avoid | |
| 447 // calling canAccess when a script accesses its own objects. | |
| 448 v8::HandleScope handleScope(m_isolate); | |
| 449 v8::Local<v8::Context> context = m_scriptState->context(); | |
| 450 if (token.isEmpty() || token == "null") { | |
| 451 context->UseDefaultSecurityToken(); | |
| 452 return; | |
| 453 } | |
| 454 | |
| 455 if (m_world->isIsolatedWorld()) { | |
| 456 SecurityOrigin* frameSecurityOrigin = | |
| 457 m_frame->securityContext()->getSecurityOrigin(); | |
| 458 String frameSecurityToken = frameSecurityOrigin->toString(); | |
| 459 // We need to check the return value of domainWasSetInDOM() on the | |
| 460 // frame's SecurityOrigin because, if that's the case, only | |
| 461 // SecurityOrigin::m_domain would have been modified. | |
| 462 // m_domain is not used by SecurityOrigin::toString(), so we would end | |
| 463 // up generating the same token that was already set. | |
| 464 if (frameSecurityOrigin->domainWasSetInDOM() || | |
| 465 frameSecurityToken.isEmpty() || frameSecurityToken == "null") { | |
| 466 context->UseDefaultSecurityToken(); | |
| 467 return; | |
| 468 } | |
| 469 token = frameSecurityToken + token; | |
| 470 } | |
| 471 | |
| 472 // NOTE: V8 does identity comparison in fast path, must use a symbol | |
| 473 // as the security token. | |
| 474 context->SetSecurityToken(v8AtomicString(m_isolate, token)); | |
| 475 } | |
| 476 | |
| 477 void WindowProxy::updateDocument() { | |
| 478 DCHECK(m_world->isMainWorld()); | |
| 479 // For an uninitialized main window proxy, there's nothing we need | |
| 480 // to update. The update is done when the window proxy gets initialized later. | |
| 481 if (m_lifecycle == Lifecycle::ContextUninitialized) | |
| 482 return; | |
| 483 // TODO(yukishiino): Is it okay to not update document when the context | |
| 484 // is detached? It's not trivial to fix this because udpateDocumentProperty | |
| 485 // requires a not-yet-detached context to instantiate a document wrapper. | |
| 486 if (m_lifecycle == Lifecycle::ContextDetached) | |
| 487 return; | |
| 488 | |
| 489 updateActivityLogger(); | |
| 490 updateDocumentProperty(); | |
| 491 updateSecurityOrigin(m_frame->securityContext()->getSecurityOrigin()); | |
| 492 } | |
| 493 | |
| 494 static v8::Local<v8::Value> getNamedProperty( | |
| 495 HTMLDocument* htmlDocument, | |
| 496 const AtomicString& key, | |
| 497 v8::Local<v8::Object> creationContext, | |
| 498 v8::Isolate* isolate) { | |
| 499 if (!htmlDocument->hasNamedItem(key) && !htmlDocument->hasExtraNamedItem(key)) | |
| 500 return v8Undefined(); | |
| 501 | |
| 502 DocumentNameCollection* items = htmlDocument->documentNamedItems(key); | |
| 503 if (items->isEmpty()) | |
| 504 return v8Undefined(); | |
| 505 | |
| 506 if (items->hasExactlyOneItem()) { | |
| 507 HTMLElement* element = items->item(0); | |
| 508 ASSERT(element); | |
| 509 Frame* frame = isHTMLIFrameElement(*element) | |
| 510 ? toHTMLIFrameElement(*element).contentFrame() | |
| 511 : 0; | |
| 512 if (frame) | |
| 513 return ToV8(frame->domWindow(), creationContext, isolate); | |
| 514 return ToV8(element, creationContext, isolate); | |
| 515 } | |
| 516 return ToV8(items, creationContext, isolate); | |
| 517 } | |
| 518 | |
| 519 static void getter(v8::Local<v8::Name> property, | |
| 520 const v8::PropertyCallbackInfo<v8::Value>& info) { | |
| 521 if (!property->IsString()) | |
| 522 return; | |
| 523 // FIXME: Consider passing StringImpl directly. | |
| 524 AtomicString name = toCoreAtomicString(property.As<v8::String>()); | |
| 525 HTMLDocument* htmlDocument = V8HTMLDocument::toImpl(info.Holder()); | |
| 526 ASSERT(htmlDocument); | |
| 527 v8::Local<v8::Value> result = | |
| 528 getNamedProperty(htmlDocument, name, info.Holder(), info.GetIsolate()); | |
| 529 if (!result.IsEmpty()) { | |
| 530 v8SetReturnValue(info, result); | |
| 531 return; | |
| 532 } | |
| 533 v8::Local<v8::Value> value; | |
| 534 if (info.Holder() | |
| 535 ->GetRealNamedPropertyInPrototypeChain( | |
| 536 info.GetIsolate()->GetCurrentContext(), property.As<v8::String>()) | |
| 537 .ToLocal(&value)) | |
| 538 v8SetReturnValue(info, value); | |
| 539 } | |
| 540 | |
| 541 void WindowProxy::namedItemAdded(HTMLDocument* document, | |
| 542 const AtomicString& name) { | |
| 543 DCHECK(m_world->isMainWorld()); | |
| 544 | |
| 545 // Context must be initialized before this point. | |
| 546 DCHECK(m_lifecycle >= Lifecycle::ContextInitialized); | |
| 547 // TODO(yukishiino): Is it okay to not update named properties | |
| 548 // after the context gets detached? | |
| 549 if (m_lifecycle == Lifecycle::ContextDetached) | |
| 550 return; | |
| 551 | |
| 552 ScriptState::Scope scope(m_scriptState.get()); | |
| 553 v8::Local<v8::Object> documentWrapper = | |
| 554 m_world->domDataStore().get(document, m_isolate); | |
| 555 // TODO(yukishiino,peria): We should check if the own property with the same | |
| 556 // name already exists or not, and if it exists, we shouldn't define a new | |
| 557 // accessor property (it fails). | |
| 558 documentWrapper->SetAccessor(m_isolate->GetCurrentContext(), | |
| 559 v8String(m_isolate, name), getter); | |
| 560 } | |
| 561 | |
| 562 void WindowProxy::namedItemRemoved(HTMLDocument* document, | |
| 563 const AtomicString& name) { | |
| 564 DCHECK(m_world->isMainWorld()); | |
| 565 | |
| 566 // Context must be initialized before this point. | |
| 567 DCHECK(m_lifecycle >= Lifecycle::ContextInitialized); | |
| 568 // TODO(yukishiino): Is it okay to not update named properties | |
| 569 // after the context gets detached? | |
| 570 if (m_lifecycle == Lifecycle::ContextDetached) | |
| 571 return; | |
| 572 | |
| 573 if (document->hasNamedItem(name) || document->hasExtraNamedItem(name)) | |
| 574 return; | |
| 575 ScriptState::Scope scope(m_scriptState.get()); | |
| 576 v8::Local<v8::Object> documentWrapper = | |
| 577 m_world->domDataStore().get(document, m_isolate); | |
| 578 documentWrapper | |
| 579 ->Delete(m_isolate->GetCurrentContext(), v8String(m_isolate, name)) | |
| 580 .ToChecked(); | |
| 581 } | |
| 582 | |
| 583 void WindowProxy::updateSecurityOrigin(SecurityOrigin* origin) { | |
| 584 // For an uninitialized main window proxy, there's nothing we need | |
| 585 // to update. The update is done when the window proxy gets initialized later. | |
| 586 if (m_lifecycle == Lifecycle::ContextUninitialized) | |
| 587 return; | |
| 588 // TODO(yukishiino): Is it okay to not update security origin when the context | |
| 589 // is detached? | |
| 590 if (m_lifecycle == Lifecycle::ContextDetached) | |
| 591 return; | |
| 592 | |
| 593 setSecurityToken(origin); | |
| 594 } | |
| 595 | |
| 596 } // namespace blink | 245 } // namespace blink |
| OLD | NEW |