Add bindings code for RemoteDOMWindow
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 Apr 2018 16:59:34 +0000 (16:59 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 17 Apr 2018 16:59:34 +0000 (16:59 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184653

Reviewed by Ryosuke Niwa.

Add bindings code for RemoteDOMWindow. A RemoteDOMWindow behaves exactly like a cross-origin
DOMWindow, which is backed by a RemoteDOMWindow object instead of a DOMWindow one. Since
a RemoteDOMWindow is always cross origin, we do not need cross-origin checks and the bindings
code is identical to the DOMWindow code paths from cross-origin handling.

No new tests, this code will be used and tested via Bug 184515.

* CMakeLists.txt:
* DerivedSources.make:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSBindingsAllInOne.cpp:
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::jsDOMWindowGetOwnPropertySlotRestrictedAccess):
(WebCore::JSDOMWindow::getOwnPropertySlot):
(WebCore::JSDOMWindow::getOwnPropertySlotByIndex):
(WebCore::addCrossOriginWindowOwnPropertyNames):
* bindings/js/JSDOMWindowCustom.h:

* bindings/js/JSRemoteDOMWindowBase.cpp: Added.
(WebCore::JSRemoteDOMWindowBase::JSRemoteDOMWindowBase):
(WebCore::JSRemoteDOMWindowBase::destroy):
(WebCore::JSRemoteDOMWindowBase::javaScriptRuntimeFlags):
(WebCore::toJS):
(WebCore::toJSRemoteDOMWindow):
* bindings/js/JSRemoteDOMWindowBase.h: Added.
JSRemoteDOMWindow unfortunately currently needs to be a global object because of:
1. a JSProxy's target needs to be a JSGlobalObject currently
2. The 'structure()->setGlobalObject(vm, &window);' call in
   JSDOMWindowProxy::setWindow(VM&, JSDOMGlobalObject&) which requires a JSGlobalObject.
Ideally, this wouldn't be the case in the future but this would require some code refactoring.
Our DOM global objects normally subclass JSDOMGlobalObject so I decided to subclass JSDOMGlobalObject,
which brings some things our bindings code expect. However, subclassing JSDOMGlobalObject directly is
problematic because it does not hold the m_wrapped implementation pointer. To address this issue, all
our our DOM global objects have a JS*Base base class which subclasses JSDOMGlobalObject and stores the
m_wrapped implementation pointer. I followed the same pattern here.

(WebCore::toJS):
* bindings/js/JSRemoteDOMWindowCustom.cpp: Added.
(WebCore::JSRemoteDOMWindow::getOwnPropertySlot):
(WebCore::JSRemoteDOMWindow::getOwnPropertySlotByIndex):
(WebCore::JSRemoteDOMWindow::put):
(WebCore::JSRemoteDOMWindow::putByIndex):
(WebCore::JSRemoteDOMWindow::deleteProperty):
(WebCore::JSRemoteDOMWindow::deletePropertyByIndex):
(WebCore::JSRemoteDOMWindow::getOwnPropertyNames):
(WebCore::JSRemoteDOMWindow::defineOwnProperty):
(WebCore::JSRemoteDOMWindow::getPrototype):
(WebCore::JSRemoteDOMWindow::preventExtensions):
(WebCore::JSRemoteDOMWindow::toStringName):
* bindings/scripts/CodeGeneratorJS.pm:
(IsDOMGlobalObject):
(GenerateHeader):
(GenerateOverloadDispatcher):
(GenerateImplementation):
* page/RemoteDOMWindow.idl: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230715 268f45cc-cd09-0410-ab3c-d52691b4dbfc

25 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/DerivedSources.make
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
Source/WebCore/bindings/js/JSDOMWindowBase.cpp
Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
Source/WebCore/bindings/js/JSDOMWindowCustom.h
Source/WebCore/bindings/js/JSDOMWindowProxy.cpp
Source/WebCore/bindings/js/JSDOMWindowProxy.h
Source/WebCore/bindings/js/JSRemoteDOMWindowBase.cpp [new file with mode: 0644]
Source/WebCore/bindings/js/JSRemoteDOMWindowBase.h [new file with mode: 0644]
Source/WebCore/bindings/js/JSRemoteDOMWindowCustom.cpp [new file with mode: 0644]
Source/WebCore/bindings/js/ScriptCachedFrameData.cpp
Source/WebCore/bindings/js/ScriptController.cpp
Source/WebCore/bindings/js/ScriptController.h
Source/WebCore/bindings/js/ScriptModuleLoader.cpp
Source/WebCore/bindings/js/WindowProxyController.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/page/RemoteDOMWindow.idl [new file with mode: 0644]
Source/WebKitLegacy/mac/DOM/DOMAbstractView.mm
Source/WebKitLegacy/mac/DOM/DOMAbstractViewInternal.h
Source/WebKitLegacy/mac/WebView/WebFrame.mm
Source/WebKitLegacy/win/WebFrame.cpp

index 7a8a12d..0c532a4 100644 (file)
@@ -820,6 +820,7 @@ set(WebCore_NON_SVG_IDL_FILES
     page/PerformanceNavigation.idl
     page/PerformanceResourceTiming.idl
     page/PerformanceTiming.idl
+    page/RemoteDOMWindow.idl
     page/Screen.idl
     page/ScrollToOptions.idl
     page/VisualViewport.idl
index 4191e1a..673dcf4 100644 (file)
@@ -1,3 +1,67 @@
+2018-04-17  Chris Dumez  <cdumez@apple.com>
+
+        Add bindings code for RemoteDOMWindow
+        https://bugs.webkit.org/show_bug.cgi?id=184653
+
+        Reviewed by Ryosuke Niwa.
+
+        Add bindings code for RemoteDOMWindow. A RemoteDOMWindow behaves exactly like a cross-origin
+        DOMWindow, which is backed by a RemoteDOMWindow object instead of a DOMWindow one. Since
+        a RemoteDOMWindow is always cross origin, we do not need cross-origin checks and the bindings
+        code is identical to the DOMWindow code paths from cross-origin handling.
+
+        No new tests, this code will be used and tested via Bug 184515.
+
+        * CMakeLists.txt:
+        * DerivedSources.make:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSBindingsAllInOne.cpp:
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::jsDOMWindowGetOwnPropertySlotRestrictedAccess):
+        (WebCore::JSDOMWindow::getOwnPropertySlot):
+        (WebCore::JSDOMWindow::getOwnPropertySlotByIndex):
+        (WebCore::addCrossOriginWindowOwnPropertyNames):
+        * bindings/js/JSDOMWindowCustom.h:
+
+        * bindings/js/JSRemoteDOMWindowBase.cpp: Added.
+        (WebCore::JSRemoteDOMWindowBase::JSRemoteDOMWindowBase):
+        (WebCore::JSRemoteDOMWindowBase::destroy):
+        (WebCore::JSRemoteDOMWindowBase::javaScriptRuntimeFlags):
+        (WebCore::toJS):
+        (WebCore::toJSRemoteDOMWindow):
+        * bindings/js/JSRemoteDOMWindowBase.h: Added.
+        JSRemoteDOMWindow unfortunately currently needs to be a global object because of:
+        1. a JSProxy's target needs to be a JSGlobalObject currently
+        2. The 'structure()->setGlobalObject(vm, &window);' call in
+           JSDOMWindowProxy::setWindow(VM&, JSDOMGlobalObject&) which requires a JSGlobalObject.
+        Ideally, this wouldn't be the case in the future but this would require some code refactoring.
+        Our DOM global objects normally subclass JSDOMGlobalObject so I decided to subclass JSDOMGlobalObject,
+        which brings some things our bindings code expect. However, subclassing JSDOMGlobalObject directly is
+        problematic because it does not hold the m_wrapped implementation pointer. To address this issue, all
+        our our DOM global objects have a JS*Base base class which subclasses JSDOMGlobalObject and stores the
+        m_wrapped implementation pointer. I followed the same pattern here.
+
+        (WebCore::toJS):
+        * bindings/js/JSRemoteDOMWindowCustom.cpp: Added.
+        (WebCore::JSRemoteDOMWindow::getOwnPropertySlot):
+        (WebCore::JSRemoteDOMWindow::getOwnPropertySlotByIndex):
+        (WebCore::JSRemoteDOMWindow::put):
+        (WebCore::JSRemoteDOMWindow::putByIndex):
+        (WebCore::JSRemoteDOMWindow::deleteProperty):
+        (WebCore::JSRemoteDOMWindow::deletePropertyByIndex):
+        (WebCore::JSRemoteDOMWindow::getOwnPropertyNames):
+        (WebCore::JSRemoteDOMWindow::defineOwnProperty):
+        (WebCore::JSRemoteDOMWindow::getPrototype):
+        (WebCore::JSRemoteDOMWindow::preventExtensions):
+        (WebCore::JSRemoteDOMWindow::toStringName):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (IsDOMGlobalObject):
+        (GenerateHeader):
+        (GenerateOverloadDispatcher):
+        (GenerateImplementation):
+        * page/RemoteDOMWindow.idl: Added.
+
 2018-04-17  David Kilzer  <ddkilzer@apple.com>
 
         Implement checked cast for DDResultRef once DDResultGetTypeID() is available
index f5d0e5d..c84520e 100644 (file)
@@ -783,6 +783,7 @@ JS_BINDING_IDLS = \
     $(WebCore)/page/PerformanceObserverEntryList.idl \
     $(WebCore)/page/PerformanceResourceTiming.idl \
     $(WebCore)/page/PerformanceTiming.idl \
+    $(WebCore)/page/RemoteDOMWindow.idl \
     $(WebCore)/page/Screen.idl \
     $(WebCore)/page/ScrollToOptions.idl \
     $(WebCore)/page/UserMessageHandler.idl \
index a57bb2d..627ffc0 100644 (file)
@@ -433,6 +433,8 @@ bindings/js/JSPluginElementFunctions.cpp
 bindings/js/JSPopStateEventCustom.cpp
 bindings/js/JSReadableStreamPrivateConstructors.cpp
 bindings/js/JSReadableStreamSourceCustom.cpp
+bindings/js/JSRemoteDOMWindowBase.cpp
+bindings/js/JSRemoteDOMWindowCustom.cpp
 bindings/js/JSSVGPathSegCustom.cpp
 bindings/js/JSStyleSheetCustom.cpp
 bindings/js/JSServiceWorkerClientCustom.cpp
@@ -2834,6 +2836,7 @@ JSReadableStreamDefaultController.cpp
 JSReadableStreamDefaultReader.cpp
 JSReadableStreamSink.cpp
 JSReadableStreamSource.cpp
+JSRemoteDOMWindow.cpp
 JSRequestAnimationFrameCallback.cpp
 JSRsaHashedImportParams.cpp
 JSRsaHashedKeyGenParams.cpp
index cf60567..31fbbff 100644 (file)
                46B95198207D634700A7D2DD /* GlobalFrameIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B95191207D632D00A7D2DD /* GlobalFrameIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
                46B95199207D634D00A7D2DD /* RemoteDOMWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B9518E207D632A00A7D2DD /* RemoteDOMWindow.h */; settings = {ATTRIBUTES = (Private, ); }; };
                46B9519A207D635400A7D2DD /* RemoteFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 46B95192207D632E00A7D2DD /* RemoteFrame.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               46BCBBC22085008F00710638 /* JSRemoteDOMWindowBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 46BCBBC02085007F00710638 /* JSRemoteDOMWindowBase.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               46C376622085177D00C73829 /* JSRemoteDOMWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 46C376612085176D00C73829 /* JSRemoteDOMWindow.h */; };
                46C696CB1E7205F700597937 /* CPUMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 46C696C91E7205E400597937 /* CPUMonitor.h */; settings = {ATTRIBUTES = (Private, ); }; };
                46C696CC1E7205FC00597937 /* CPUMonitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46C696CA1E7205E400597937 /* CPUMonitor.cpp */; };
                46C83EFE1A9BBE2900A79A41 /* GeoNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 46C83EFC1A9BBE2900A79A41 /* GeoNotifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
                46B95192207D632E00A7D2DD /* RemoteFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteFrame.h; sourceTree = "<group>"; };
                46B95193207D632F00A7D2DD /* AbstractDOMWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractDOMWindow.cpp; sourceTree = "<group>"; };
                46B95194207D633000A7D2DD /* AbstractFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AbstractFrame.cpp; sourceTree = "<group>"; };
+               46BCBBBE2085005B00710638 /* JSRemoteDOMWindowCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSRemoteDOMWindowCustom.cpp; sourceTree = "<group>"; };
+               46BCBBC02085007F00710638 /* JSRemoteDOMWindowBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRemoteDOMWindowBase.h; sourceTree = "<group>"; };
+               46BCBBC12085008000710638 /* JSRemoteDOMWindowBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSRemoteDOMWindowBase.cpp; sourceTree = "<group>"; };
+               46BCBBC3208500A700710638 /* RemoteDOMWindow.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RemoteDOMWindow.idl; sourceTree = "<group>"; };
+               46C3765F2085176C00C73829 /* JSRemoteDOMWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSRemoteDOMWindow.cpp; sourceTree = "<group>"; };
+               46C376612085176D00C73829 /* JSRemoteDOMWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRemoteDOMWindow.h; sourceTree = "<group>"; };
                46C696C91E7205E400597937 /* CPUMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CPUMonitor.h; sourceTree = "<group>"; };
                46C696CA1E7205E400597937 /* CPUMonitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CPUMonitor.cpp; sourceTree = "<group>"; };
                46C83EFB1A9BBE2900A79A41 /* GeoNotifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GeoNotifier.cpp; sourceTree = "<group>"; };
                                B776D43A1104525D00BEB0EC /* PrintContext.h */,
                                46B9518D207D632A00A7D2DD /* RemoteDOMWindow.cpp */,
                                46B9518E207D632A00A7D2DD /* RemoteDOMWindow.h */,
+                               46BCBBC3208500A700710638 /* RemoteDOMWindow.idl */,
                                46B9518C207D632900A7D2DD /* RemoteFrame.cpp */,
                                46B95192207D632E00A7D2DD /* RemoteFrame.h */,
                                A5071E8A1C56FAFA009951BE /* ResourceUsageData.cpp */,
                                93B70D5009EB0C7C009D8468 /* JSPluginElementFunctions.h */,
                                4129DF831BB5B7F700322A16 /* JSReadableStreamPrivateConstructors.cpp */,
                                4129DF841BB5B7F700322A16 /* JSReadableStreamPrivateConstructors.h */,
+                               46BCBBC12085008000710638 /* JSRemoteDOMWindowBase.cpp */,
+                               46BCBBC02085007F00710638 /* JSRemoteDOMWindowBase.h */,
                                931AE3B81FB80EAE00F5EFB2 /* JSValueInWrappedObject.h */,
                                E1C36D320EB0A094007410BC /* JSWorkerGlobalScopeBase.cpp */,
                                E1C36D330EB0A094007410BC /* JSWorkerGlobalScopeBase.h */,
                                BC5823F40C0A98DF0053F1B5 /* JSHTMLElementCustom.cpp */,
                                BCE1C43F0D9830F4003B02F2 /* JSLocationCustom.cpp */,
                                418C395D1C8F0AAB0051C8A3 /* JSReadableStreamSourceCustom.cpp */,
+                               46BCBBBE2085005B00710638 /* JSRemoteDOMWindowCustom.cpp */,
                        );
                        name = Custom;
                        sourceTree = "<group>";
                                CB38FD591CD2314500592A3F /* JSPerformanceResourceTiming.h */,
                                0F43C85E189E15A600019AE2 /* JSPerformanceTiming.cpp */,
                                8A9A587711E84C98008ACFD1 /* JSPerformanceTiming.h */,
+                               46C3765F2085176C00C73829 /* JSRemoteDOMWindow.cpp */,
+                               46C376612085176D00C73829 /* JSRemoteDOMWindow.h */,
                                BCEC01C00C274DDD009F4EC9 /* JSScreen.cpp */,
                                BCEC01C10C274DDD009F4EC9 /* JSScreen.h */,
                                83E9B3001DA5A51E00FFE8F6 /* JSScrollToOptions.cpp */,
                                4129DF861BB5B80C00322A16 /* JSReadableStreamPrivateConstructors.h in Headers */,
                                7F4C96DD1AD4483500365A51 /* JSReadableStreamSink.h in Headers */,
                                7E4C96DD1AD4483500365A51 /* JSReadableStreamSource.h in Headers */,
+                               46C376622085177D00C73829 /* JSRemoteDOMWindow.h in Headers */,
+                               46BCBBC22085008F00710638 /* JSRemoteDOMWindowBase.h in Headers */,
                                4998AECE13F9D6C90090B1AA /* JSRequestAnimationFrameCallback.h in Headers */,
                                57E233711DCD468F00F28D01 /* JSRsaHashedImportParams.h in Headers */,
                                5768E4341DB7524500D0A4F7 /* JSRsaHashedKeyGenParams.h in Headers */,
index cc5ce63..a85cde1 100644 (file)
@@ -86,6 +86,8 @@
 #include "JSPluginElementFunctions.cpp"
 #include "JSPopStateEventCustom.cpp"
 #include "JSReadableStreamPrivateConstructors.cpp"
+#include "JSRemoteDOMWindowBase.cpp"
+#include "JSRemoteDOMWindowCustom.cpp"
 #include "JSSVGPathSegCustom.cpp"
 #include "JSStyleSheetCustom.cpp"
 #include "JSTextCustom.cpp"
index 6fa6e7d..1bfe18a 100644 (file)
@@ -281,7 +281,7 @@ JSDOMWindow* toJSDOMWindow(JSC::VM& vm, JSValue value)
         if (classInfo == JSDOMWindow::info())
             return jsCast<JSDOMWindow*>(object);
         if (classInfo == JSDOMWindowProxy::info())
-            return jsCast<JSDOMWindowProxy*>(object)->window();
+            return jsDynamicCast<JSDOMWindow*>(vm, jsCast<JSDOMWindowProxy*>(object)->window());
         value = object->getPrototypeDirect(vm);
     }
     return nullptr;
index e589ad6..a2f6847 100644 (file)
@@ -37,6 +37,7 @@
 #include "JSHTMLCollection.h"
 #include "JSHTMLOptionElement.h"
 #include "JSIDBFactory.h"
+#include "JSRemoteDOMWindow.h"
 #include "JSWorker.h"
 #include "Location.h"
 #include "RuntimeEnabledFeatures.h"
@@ -78,7 +79,8 @@ static EncodedJSValue jsDOMWindowWebKit(ExecState* exec, EncodedJSValue thisValu
 }
 #endif
 
-static bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMWindow* thisObject, Frame* frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot, const String& errorMessage)
+template <DOMWindowType windowType>
+bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMGlobalObject* thisObject, AbstractFrame* frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot, const String& errorMessage)
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -94,26 +96,27 @@ static bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMWindow* thisObjec
     // These are the functions we allow access to cross-origin (DoNotCheckSecurity in IDL).
     // Always provide the original function, on a fresh uncached function object.
     if (propertyName == builtinNames.blurPublicName()) {
-        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionBlur, 0>);
+        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), windowType == DOMWindowType::Remote ? nonCachingStaticFunctionGetter<jsRemoteDOMWindowInstanceFunctionBlur, 0> : nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionBlur, 0>);
         return true;
     }
     if (propertyName == builtinNames.closePublicName()) {
-        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0>);
+        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), windowType == DOMWindowType::Remote ? nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0> : nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0>);
         return true;
     }
     if (propertyName == builtinNames.focusPublicName()) {
-        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionFocus, 0>);
+        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), windowType == DOMWindowType::Remote ? nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionFocus, 0> : nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionFocus, 0>);
         return true;
     }
     if (propertyName == builtinNames.postMessagePublicName()) {
-        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionPostMessage, 2>);
+        slot.setCustom(thisObject, static_cast<unsigned>(JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontEnum), windowType == DOMWindowType::Remote ? nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionPostMessage, 0> : nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionPostMessage, 2>);
         return true;
     }
 
     // When accessing cross-origin known Window properties, we always use the original property getter,
     // even if the property was removed / redefined. As of early 2016, this matches Firefox and Chrome's
     // behavior.
-    if (auto* entry = JSDOMWindow::info()->staticPropHashTable->entry(propertyName)) {
+    auto* classInfo = windowType == DOMWindowType::Remote ? JSRemoteDOMWindow::info() : JSDOMWindow::info();
+    if (auto* entry = classInfo->staticPropHashTable->entry(propertyName)) {
         // Only allow access to these specific properties.
         if (propertyName == builtinNames.locationPublicName()
             || propertyName == builtinNames.closedPublicName()
@@ -142,8 +145,9 @@ static bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMWindow* thisObjec
     // not match IE, but some sites end up naming frames things that conflict with window
     // properties that are in Moz but not IE. Since we have some of these, we have to do it
     // the Moz way.
-    if (frame) {
-        if (auto* scopedChild = frame->tree().scopedChild(propertyNameToAtomicString(propertyName))) {
+    // FIXME: Add support to named attributes on RemoteFrames.
+    if (frame && is<Frame>(*frame)) {
+        if (auto* scopedChild = downcast<Frame>(*frame).tree().scopedChild(propertyNameToAtomicString(propertyName))) {
             slot.setValue(thisObject, JSC::PropertyAttribute::ReadOnly | JSC::PropertyAttribute::DontDelete | JSC::PropertyAttribute::DontEnum, toJS(exec, scopedChild->document()->domWindow()));
             return true;
         }
@@ -153,6 +157,8 @@ static bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMWindow* thisObjec
     slot.setUndefined();
     return false;
 }
+template bool jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Local>(JSDOMGlobalObject*, AbstractFrame*, ExecState*, PropertyName, PropertySlot&, const String&);
+template bool jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(JSDOMGlobalObject*, AbstractFrame*, ExecState*, PropertyName, PropertySlot&, const String&);
 
 // Property access sequence is:
 // (1) indexed properties,
@@ -171,7 +177,7 @@ bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* state, Propert
     // Hand off all cross-domain access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
     String errorMessage;
     if (!BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage))
-        return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, state, propertyName, slot, errorMessage);
+        return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Local>(thisObject, frame, state, propertyName, slot, errorMessage);
     
     // FIXME: this need more explanation.
     // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?)
@@ -222,7 +228,7 @@ bool JSDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* state,
     // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
     String errorMessage;
     if (!BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage))
-        return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, state, Identifier::from(state, index), slot, errorMessage);
+        return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Local>(thisObject, frame, state, Identifier::from(state, index), slot, errorMessage);
 
     // (2) Regular own properties.
     return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
@@ -318,7 +324,7 @@ static void addScopedChildrenIndexes(ExecState& state, DOMWindow& window, Proper
 }
 
 // https://html.spec.whatwg.org/#crossoriginownpropertykeys-(-o-)
-static void addCrossOriginWindowOwnPropertyNames(ExecState& state, PropertyNameArray& propertyNames)
+void addCrossOriginWindowOwnPropertyNames(ExecState& state, PropertyNameArray& propertyNames)
 {
     VM& vm = state.vm();
     addCrossOriginWindowPropertyNames(vm, propertyNames);
@@ -461,8 +467,10 @@ DOMWindow* JSDOMWindow::toWrapped(VM& vm, JSValue value)
     JSObject* object = asObject(value);
     if (object->inherits<JSDOMWindow>(vm))
         return &jsCast<JSDOMWindow*>(object)->wrapped();
-    if (object->inherits<JSDOMWindowProxy>(vm))
-        return &jsCast<JSDOMWindowProxy*>(object)->wrapped();
+    if (object->inherits<JSDOMWindowProxy>(vm)) {
+        if (auto* jsDOMWindow = jsDynamicCast<JSDOMWindow*>(vm, jsCast<JSDOMWindowProxy*>(object)->window()))
+            return &jsDOMWindow->wrapped();
+    }
     return nullptr;
 }
 
index ebfc54a..cfda3e0 100644 (file)
 
 namespace WebCore {
 
+class AbstractFrame;
+
 inline JSDOMWindow* asJSDOMWindow(JSC::JSGlobalObject* globalObject)
 {
     return JSC::jsCast<JSDOMWindow*>(globalObject);
 }
+
 inline const JSDOMWindow* asJSDOMWindow(const JSC::JSGlobalObject* globalObject)
 {
     return static_cast<const JSDOMWindow*>(globalObject);
 }
 
+enum class DOMWindowType { Local, Remote };
+
+template <DOMWindowType windowType>
+bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMGlobalObject*, AbstractFrame*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&, const String&);
+
+void addCrossOriginWindowOwnPropertyNames(JSC::ExecState&, JSC::PropertyNameArray&);
+
 } // namespace WebCore
index 39df5be..2086b3d 100644 (file)
@@ -69,40 +69,50 @@ void JSDOMWindowProxy::destroy(JSCell* cell)
     static_cast<JSDOMWindowProxy*>(cell)->JSDOMWindowProxy::~JSDOMWindowProxy();
 }
 
-void JSDOMWindowProxy::setWindow(VM& vm, JSDOMWindow& window)
+void JSDOMWindowProxy::setWindow(VM& vm, JSDOMGlobalObject& window)
 {
+    ASSERT(window.classInfo() == JSDOMWindow::info() || window.classInfo() == JSRemoteDOMWindow::info());
     setTarget(vm, &window);
     structure()->setGlobalObject(vm, &window);
     GCController::singleton().garbageCollectSoon();
 }
 
-void JSDOMWindowProxy::setWindow(DOMWindow& domWindow)
+void JSDOMWindowProxy::setWindow(AbstractDOMWindow& domWindow)
 {
     // Replacing JSDOMWindow via telling JSDOMWindowProxy to use the same DOMWindow it already uses makes no sense,
     // so we'd better never try to.
-    ASSERT(!window() || &domWindow != &window()->wrapped());
+    ASSERT(!window() || &domWindow != &wrapped());
+
+    bool isRemoteDOMWindow = is<RemoteDOMWindow>(domWindow);
 
     VM& vm = commonVM();
-    auto& prototypeStructure = *JSDOMWindowPrototype::createStructure(vm, nullptr, jsNull());
+    auto& prototypeStructure = isRemoteDOMWindow ? *JSRemoteDOMWindowPrototype::createStructure(vm, nullptr, jsNull()) : *JSDOMWindowPrototype::createStructure(vm, nullptr, jsNull());
 
     // Explicitly protect the prototype so it isn't collected when we allocate the global object.
     // (Once the global object is fully constructed, it will mark its own prototype.)
     // FIXME: Why do we need to protect this when there's a pointer to it on the stack?
     // Perhaps the issue is that structure objects aren't seen when scanning the stack?
-    Strong<JSDOMWindowPrototype> prototype(vm, JSDOMWindowPrototype::create(vm, nullptr, &prototypeStructure));
+    Strong<JSNonFinalObject> prototype(vm, isRemoteDOMWindow ? static_cast<JSNonFinalObject*>(JSRemoteDOMWindowPrototype::create(vm, nullptr, &prototypeStructure)) : static_cast<JSNonFinalObject*>(JSDOMWindowPrototype::create(vm, nullptr, &prototypeStructure)));
+
+    JSDOMGlobalObject* window = nullptr;
+    if (isRemoteDOMWindow) {
+        auto& windowStructure = *JSRemoteDOMWindow::createStructure(vm, nullptr, prototype.get());
+        window = JSRemoteDOMWindow::create(vm, &windowStructure, downcast<RemoteDOMWindow>(domWindow), this);
+    } else {
+        auto& windowStructure = *JSDOMWindow::createStructure(vm, nullptr, prototype.get());
+        window = JSDOMWindow::create(vm, &windowStructure, downcast<DOMWindow>(domWindow), this);
+    }
 
-    auto& windowStructure = *JSDOMWindow::createStructure(vm, nullptr, prototype.get());
-    auto& window = *JSDOMWindow::create(vm, &windowStructure, domWindow, this);
-    prototype->structure()->setGlobalObject(vm, &window);
+    prototype->structure()->setGlobalObject(vm, window);
 
-    auto& propertiesStructure = *JSDOMWindowProperties::createStructure(vm, &window, JSEventTarget::prototype(vm, window));
-    auto& properties = *JSDOMWindowProperties::create(&propertiesStructure, window);
+    auto& propertiesStructure = *JSDOMWindowProperties::createStructure(vm, window, JSEventTarget::prototype(vm, *window));
+    auto& properties = *JSDOMWindowProperties::create(&propertiesStructure, *window);
     prototype->structure()->setPrototypeWithoutTransition(vm, &properties);
 
-    setWindow(vm, window);
+    setWindow(vm, *window);
 
-    ASSERT(window.globalObject() == &window);
-    ASSERT(prototype->globalObject() == &window);
+    ASSERT(window->globalObject() == window);
+    ASSERT(prototype->globalObject() == window);
 }
 
 void JSDOMWindowProxy::attachDebugger(JSC::Debugger* debugger)
@@ -116,23 +126,26 @@ void JSDOMWindowProxy::attachDebugger(JSC::Debugger* debugger)
         currentDebugger->detach(globalObject, JSC::Debugger::TerminatingDebuggingSession);
 }
 
-DOMWindow& JSDOMWindowProxy::wrapped() const
+AbstractDOMWindow& JSDOMWindowProxy::wrapped() const
 {
-    return window()->wrapped();
+    auto* window = this->window();
+    if (auto* jsWindow = jsDynamicCast<JSRemoteDOMWindowBase*>(window->vm(), window))
+        return jsWindow->wrapped();
+    return jsCast<JSDOMWindowBase*>(window)->wrapped();
 }
 
-DOMWindow* JSDOMWindowProxy::toWrapped(VM& vm, JSObject* value)
+AbstractDOMWindow* JSDOMWindowProxy::toWrapped(VM& vm, JSObject* value)
 {
     auto* wrapper = jsDynamicCast<JSDOMWindowProxy*>(vm, value);
-    return wrapper ? &wrapper->window()->wrapped() : nullptr;
+    return wrapper ? &wrapper->wrapped() : nullptr;
 }
 
-JSValue toJS(ExecState* state, Frame& frame)
+JSValue toJS(ExecState* state, AbstractFrame& frame)
 {
     return &frame.windowProxyController().windowProxy(currentWorld(*state));
 }
 
-JSDOMWindowProxy& toJSDOMWindowProxy(Frame& frame, DOMWrapperWorld& world)
+JSDOMWindowProxy& toJSDOMWindowProxy(AbstractFrame& frame, DOMWrapperWorld& world)
 {
     return frame.windowProxyController().windowProxy(world);
 }
index 7e55497..13fb325 100644 (file)
@@ -37,7 +37,8 @@ class Debugger;
 
 namespace WebCore {
 
-class Frame;
+class AbstractDOMWindow;
+class AbstractFrame;
 
 class JSDOMWindowProxy final : public JSC::JSProxy {
     using Base = JSC::JSProxy;
@@ -47,12 +48,12 @@ public:
 
     DECLARE_INFO;
 
-    JSDOMWindow* window() const { return JSC::jsCast<JSDOMWindow*>(target()); }
-    void setWindow(JSC::VM&, JSDOMWindow&);
-    void setWindow(DOMWindow&);
+    JSDOMGlobalObject* window() const { return JSC::jsCast<JSDOMGlobalObject*>(target()); }
+    void setWindow(JSC::VM&, JSDOMGlobalObject&);
+    void setWindow(AbstractDOMWindow&);
 
-    DOMWindow& wrapped() const;
-    static WEBCORE_EXPORT DOMWindow* toWrapped(JSC::VM&, JSC::JSObject*);
+    AbstractDOMWindow& wrapped() const;
+    static WEBCORE_EXPORT AbstractDOMWindow* toWrapped(JSC::VM&, JSC::JSObject*);
 
     DOMWrapperWorld& world() { return m_world; }
 
@@ -67,10 +68,10 @@ private:
 
 // JSDOMWindowProxy is a little odd in that it's not a traditional wrapper and has no back pointer.
 // It is, however, strongly owned by Frame via its ScriptController, so we can get one from a frame.
-JSC::JSValue toJS(JSC::ExecState*, Frame&);
-inline JSC::JSValue toJS(JSC::ExecState* state, Frame* frame) { return frame ? toJS(state, *frame) : JSC::jsNull(); }
+JSC::JSValue toJS(JSC::ExecState*, AbstractFrame&);
+inline JSC::JSValue toJS(JSC::ExecState* state, AbstractFrame* frame) { return frame ? toJS(state, *frame) : JSC::jsNull(); }
 
-JSDOMWindowProxy& toJSDOMWindowProxy(Frame&, DOMWrapperWorld&);
-inline JSDOMWindowProxy* toJSDOMWindowProxy(Frame* frame, DOMWrapperWorld& world) { return frame ? &toJSDOMWindowProxy(*frame, world) : nullptr; }
+JSDOMWindowProxy& toJSDOMWindowProxy(AbstractFrame&, DOMWrapperWorld&);
+inline JSDOMWindowProxy* toJSDOMWindowProxy(AbstractFrame* frame, DOMWrapperWorld& world) { return frame ? &toJSDOMWindowProxy(*frame, world) : nullptr; }
 
 } // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSRemoteDOMWindowBase.cpp b/Source/WebCore/bindings/js/JSRemoteDOMWindowBase.cpp
new file mode 100644 (file)
index 0000000..cbd2d36
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSRemoteDOMWindowBase.h"
+
+#include "JSDOMWindowProxy.h"
+#include "JSRemoteDOMWindow.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+const ClassInfo JSRemoteDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSRemoteDOMWindowBase) };
+
+const GlobalObjectMethodTable JSRemoteDOMWindowBase::s_globalObjectMethodTable = {
+    nullptr, // shellSupportsRichSourceInfo
+    nullptr, // shouldInterruptScript
+    &javaScriptRuntimeFlags,
+    nullptr, // queueTaskToEventLoop
+    nullptr, // shouldInterruptScriptBeforeTimeout
+    nullptr, // moduleLoaderImportModule
+    nullptr, // moduleLoaderResolve
+    nullptr, // moduleLoaderFetch
+    nullptr, // moduleLoaderCreateImportMetaProperties
+    nullptr, // moduleLoaderEvaluate
+    nullptr, // promiseRejectionTracker
+    nullptr, // defaultLanguage
+};
+
+JSRemoteDOMWindowBase::JSRemoteDOMWindowBase(VM& vm, Structure* structure, RefPtr<RemoteDOMWindow>&& window, JSDOMWindowProxy* proxy)
+    : JSDOMGlobalObject(vm, structure, proxy->world(), &s_globalObjectMethodTable)
+    , m_wrapped(WTFMove(window))
+{
+}
+
+void JSRemoteDOMWindowBase::destroy(JSCell* cell)
+{
+    static_cast<JSRemoteDOMWindowBase*>(cell)->JSRemoteDOMWindowBase::~JSRemoteDOMWindowBase();
+}
+
+RuntimeFlags JSRemoteDOMWindowBase::javaScriptRuntimeFlags(const JSGlobalObject*)
+{
+    return RuntimeFlags { };
+}
+
+JSValue toJS(ExecState* state, JSDOMGlobalObject*, RemoteDOMWindow& domWindow)
+{
+    return toJS(state, domWindow);
+}
+
+JSValue toJS(ExecState* state, RemoteDOMWindow& domWindow)
+{
+    return toJS(state, domWindow.frame());
+}
+
+JSRemoteDOMWindow* toJSRemoteDOMWindow(JSC::VM& vm, JSValue value)
+{
+    if (!value.isObject())
+        return nullptr;
+
+    while (!value.isNull()) {
+        JSObject* object = asObject(value);
+        const ClassInfo* classInfo = object->classInfo(vm);
+        if (classInfo == JSRemoteDOMWindow::info())
+            return jsCast<JSRemoteDOMWindow*>(object);
+        if (classInfo == JSDOMWindowProxy::info())
+            return jsDynamicCast<JSRemoteDOMWindow*>(vm, jsCast<JSDOMWindowProxy*>(object)->window());
+        value = object->getPrototypeDirect(vm);
+    }
+    return nullptr;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSRemoteDOMWindowBase.h b/Source/WebCore/bindings/js/JSRemoteDOMWindowBase.h
new file mode 100644 (file)
index 0000000..a3c6b05
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSDOMGlobalObject.h"
+#include "RemoteDOMWindow.h"
+#include <JavaScriptCore/StructureInlines.h>
+
+namespace WebCore {
+
+class JSDOMWindowProxy;
+class JSRemoteDOMWindow;
+
+class WEBCORE_EXPORT JSRemoteDOMWindowBase : public JSDOMGlobalObject {
+protected:
+    JSRemoteDOMWindowBase(JSC::VM&, JSC::Structure*, RefPtr<RemoteDOMWindow>&&, JSDOMWindowProxy*);
+
+    static void destroy(JSCell*);
+
+public:
+    RemoteDOMWindow& wrapped() const { return *m_wrapped; }
+
+    DECLARE_INFO;
+
+    static const JSC::GlobalObjectMethodTable s_globalObjectMethodTable;
+
+    static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*);
+
+private:
+    RefPtr<RemoteDOMWindow> m_wrapped;
+};
+
+WEBCORE_EXPORT JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, RemoteDOMWindow&);
+inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, RemoteDOMWindow* window) { return window ? toJS(state, globalObject, *window) : JSC::jsNull(); }
+
+JSC::JSValue toJS(JSC::ExecState*, RemoteDOMWindow&);
+inline JSC::JSValue toJS(JSC::ExecState* state, RemoteDOMWindow* window) { return window ? toJS(state, *window) : JSC::jsNull(); }
+
+WEBCORE_EXPORT JSRemoteDOMWindow* toJSRemoteDOMWindow(JSC::VM&, JSC::JSValue);
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSRemoteDOMWindowCustom.cpp b/Source/WebCore/bindings/js/JSRemoteDOMWindowCustom.cpp
new file mode 100644 (file)
index 0000000..b7f7ae9
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSRemoteDOMWindow.h"
+
+#include "JSDOMWindowCustom.h"
+#include "WebCoreJSClientData.h"
+
+namespace WebCore {
+
+bool JSRemoteDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
+{
+    if (std::optional<unsigned> index = parseIndex(propertyName))
+        return getOwnPropertySlotByIndex(object, state, index.value(), slot);
+
+    auto* thisObject = jsCast<JSRemoteDOMWindow*>(object);
+    auto* frame = thisObject->wrapped().frame();
+
+    return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(thisObject, frame, state, propertyName, slot, String());
+}
+
+bool JSRemoteDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
+{
+    auto* thisObject = jsCast<JSRemoteDOMWindow*>(object);
+    auto* frame = thisObject->wrapped().frame();
+
+    // Indexed getters take precendence over regular properties, so caching would be invalid.
+    slot.disableCaching();
+
+    // FIXME: Add support for indexed properties.
+
+    return jsDOMWindowGetOwnPropertySlotRestrictedAccess<DOMWindowType::Remote>(thisObject, frame, state, Identifier::from(state, index), slot, String());
+}
+
+bool JSRemoteDOMWindow::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+{
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto* thisObject = jsCast<JSRemoteDOMWindow*>(cell);
+    if (!thisObject->wrapped().frame())
+        return false;
+
+    String errorMessage;
+
+    // We only allow setting "location" attribute cross-origin.
+    if (propertyName == static_cast<JSVMClientData*>(vm.clientData)->builtinNames().locationPublicName()) {
+        bool putResult = false;
+        if (lookupPut(state, propertyName, thisObject, value, *s_info.staticPropHashTable, slot, putResult))
+            return putResult;
+        return false;
+    }
+    throwSecurityError(*state, scope, errorMessage);
+    return false;
+}
+
+bool JSRemoteDOMWindow::putByIndex(JSCell*, ExecState*, unsigned, JSValue, bool)
+{
+    return false;
+}
+
+bool JSRemoteDOMWindow::deleteProperty(JSCell*, ExecState* state, PropertyName)
+{
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    throwSecurityError(*state, scope, String());
+    return false;
+}
+
+bool JSRemoteDOMWindow::deletePropertyByIndex(JSCell*, ExecState* state, unsigned)
+{
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    throwSecurityError(*state, scope, String());
+    return false;
+}
+
+void JSRemoteDOMWindow::getOwnPropertyNames(JSObject*, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+    // FIXME: Add scoped children indexes.
+
+    if (mode.includeDontEnumProperties())
+        addCrossOriginWindowOwnPropertyNames(*exec, propertyNames);
+}
+
+bool JSRemoteDOMWindow::defineOwnProperty(JSC::JSObject*, JSC::ExecState* state, JSC::PropertyName, const JSC::PropertyDescriptor&, bool)
+{
+    VM& vm = state->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    throwSecurityError(*state, scope, String());
+    return false;
+}
+
+JSValue JSRemoteDOMWindow::getPrototype(JSObject*, ExecState*)
+{
+    return jsNull();
+}
+
+bool JSRemoteDOMWindow::preventExtensions(JSObject*, ExecState* exec)
+{
+    auto scope = DECLARE_THROW_SCOPE(exec->vm());
+    throwTypeError(exec, scope, ASCIILiteral("Cannot prevent extensions on this object"));
+    return false;
+}
+
+String JSRemoteDOMWindow::toStringName(const JSObject*, ExecState*)
+{
+    return ASCIILiteral("Object");
+}
+
+} // namepace WebCore
index 86456a7..4a7c988 100644 (file)
@@ -52,7 +52,7 @@ ScriptCachedFrameData::ScriptCachedFrameData(Frame& frame)
     JSLockHolder lock(commonVM());
 
     for (auto windowProxy : frame.windowProxyController().windowProxiesAsVector()) {
-        auto* window = windowProxy->window();
+        auto* window = jsCast<JSDOMWindow*>(windowProxy->window());
         m_windows.add(&windowProxy->world(), Strong<JSDOMWindow>(window->vm(), window));
         window->setConsoleClient(nullptr);
     }
@@ -79,7 +79,7 @@ void ScriptCachedFrameData::restore(Frame& frame)
         else {
             ASSERT(frame.document()->domWindow());
             auto& domWindow = *frame.document()->domWindow();
-            if (&windowProxy->window()->wrapped() == &domWindow)
+            if (&windowProxy->wrapped() == &domWindow)
                 continue;
 
             windowProxy->setWindow(domWindow);
index bb58c08..ef65c9d 100644 (file)
@@ -244,7 +244,7 @@ void ScriptController::initScriptForWindowProxy(JSDOMWindowProxy& windowProxy)
 {
     auto& world = windowProxy.world();
 
-    windowProxy.window()->updateDocument();
+    jsCast<JSDOMWindow*>(windowProxy.window())->updateDocument();
 
     if (Document* document = m_frame.document())
         document->contentSecurityPolicy()->didCreateWindowProxy(windowProxy);
@@ -385,7 +385,7 @@ void ScriptController::updateDocument()
 {
     for (auto& windowProxy : windowProxyController().windowProxiesAsVector()) {
         JSLockHolder lock(windowProxy->world().vm());
-        windowProxy->window()->updateDocument();
+        jsCast<JSDOMWindow*>(windowProxy->window())->updateDocument();
     }
 }
 
@@ -429,7 +429,7 @@ void ScriptController::collectIsolatedContexts(Vector<std::pair<JSC::ExecState*,
 {
     for (auto& windowProxy : windowProxyController().windowProxiesAsVector()) {
         auto* exec = windowProxy->window()->globalExec();
-        auto* origin = &windowProxy->window()->wrapped().document()->securityOrigin();
+        auto* origin = &downcast<DOMWindow>(windowProxy->wrapped()).document()->securityOrigin();
         result.append(std::make_pair(exec, origin));
     }
 }
index 0b51a08..ac9d2d0 100644 (file)
@@ -83,7 +83,7 @@ public:
 
     JSDOMWindow* globalObject(DOMWrapperWorld& world)
     {
-        return windowProxyController().windowProxy(world).window();
+        return JSC::jsCast<JSDOMWindow*>(windowProxyController().windowProxy(world).window());
     }
 
     static void getAllWorlds(Vector<Ref<DOMWrapperWorld>>&);
index d04c6f9..a6e3bc2 100644 (file)
@@ -199,7 +199,7 @@ JSC::JSValue ScriptModuleLoader::evaluate(JSC::JSGlobalObject*, JSC::ExecState*
     // FIXME: Currently, we only support JSModuleRecord.
     // Once the reflective part of the module loader is supported, we will handle arbitrary values.
     // https://whatwg.github.io/loader/#registry-prototype-provide
-    auto* moduleRecord = jsDynamicCast<JSC::JSModuleRecord*>(vm, moduleRecordValue);
+    auto* moduleRecord = JSC::jsDynamicCast<JSC::JSModuleRecord*>(vm, moduleRecordValue);
     if (!moduleRecord)
         return JSC::jsUndefined();
 
index 0fe47d4..730ec31 100644 (file)
@@ -117,7 +117,8 @@ void WindowProxyController::clearWindowProxiesNotMatchingDOMWindow(AbstractDOMWi
         // Clear the debugger and console from the current window before setting the new window.
         windowProxy->attachDebugger(nullptr);
         windowProxy->window()->setConsoleClient(nullptr);
-        windowProxy->window()->willRemoveFromWindowProxy();
+        if (auto* jsDOMWindow = jsDynamicCast<JSDOMWindowBase*>(*windowProxy->vm(), windowProxy->window()))
+            jsDOMWindow->willRemoveFromWindowProxy();
     }
 
     // It's likely that resetting our windows created a lot of garbage, unless
index 10f8773..9e1c0c9 100644 (file)
@@ -497,7 +497,7 @@ sub GetCustomIsReachable
 sub IsDOMGlobalObject
 {
     my $interface = shift;
-    return $interface->type->name eq "DOMWindow" || $codeGenerator->InheritsInterface($interface, "WorkerGlobalScope") || $interface->type->name eq "TestGlobalObject";
+    return $interface->type->name eq "DOMWindow" || $interface->type->name eq "RemoteDOMWindow" || $codeGenerator->InheritsInterface($interface, "WorkerGlobalScope") || $interface->type->name eq "TestGlobalObject";
 }
 
 sub ShouldUseGlobalObjectPrototype
@@ -2508,7 +2508,7 @@ sub GenerateHeader
         }
     }
 
-    push(@headerContent, "class JSDOMWindowProxy;\n\n") if $interfaceName eq "DOMWindow";
+    push(@headerContent, "class JSDOMWindowProxy;\n\n") if $interfaceName eq "DOMWindow" or $interfaceName eq "RemoteDOMWindow";
 
     my $exportMacro = GetExportMacroForJSClass($interface);
 
@@ -2520,7 +2520,7 @@ sub GenerateHeader
     push(@headerContent, "    using Base = $parentClassName;\n");
     push(@headerContent, "    using DOMWrapped = $implType;\n") if $hasParent;
 
-    if ($interfaceName eq "DOMWindow") {
+    if ($interfaceName eq "DOMWindow" || $interfaceName eq "RemoteDOMWindow") {
         push(@headerContent, "    static $className* create(JSC::VM& vm, JSC::Structure* structure, Ref<$implType>&& impl, JSDOMWindowProxy* proxy)\n");
         push(@headerContent, "    {\n");
         push(@headerContent, "        $className* ptr = new (NotNull, JSC::allocateCell<$className>(vm.heap)) ${className}(vm, structure, WTFMove(impl), proxy);\n");
@@ -2829,7 +2829,7 @@ sub GenerateHeader
     push(@headerContent, "protected:\n");
 
     # Constructor
-    if ($interfaceName eq "DOMWindow") {
+    if ($interfaceName eq "DOMWindow" || $interfaceName eq "RemoteDOMWindow") {
         push(@headerContent, "    $className(JSC::VM&, JSC::Structure*, Ref<$implType>&&, JSDOMWindowProxy*);\n");
     } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) {
         push(@headerContent, "    $className(JSC::VM&, JSC::Structure*, Ref<$implType>&&);\n");
@@ -2839,7 +2839,7 @@ sub GenerateHeader
         push(@headerContent, "    $className(JSC::Structure*, JSDOMGlobalObject&, Ref<$implType>&&);\n\n");
     }
 
-    if ($interfaceName eq "DOMWindow") {
+    if ($interfaceName eq "DOMWindow" || $interfaceName eq "RemoteDOMWindow") {
         push(@headerContent, "    void finishCreation(JSC::VM&, JSDOMWindowProxy*);\n");
     } elsif ($codeGenerator->InheritsInterface($interface, "WorkerGlobalScope")) {
         push(@headerContent, "    void finishCreation(JSC::VM&, JSC::JSProxy*);\n");
@@ -3401,6 +3401,9 @@ sub GenerateOverloadDispatcher
                         if ($subtype->name eq "DOMWindow") {
                             AddToImplIncludes("JSDOMWindowProxy.h");
                             &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && (asObject(distinguishingArg)->inherits<JSDOMWindowProxy>(vm) || asObject(distinguishingArg)->inherits<JSDOMWindow>(vm))");
+                        } elsif ($subtype->name eq "RemoteDOMWindow") {
+                            AddToImplIncludes("JSDOMWindowProxy.h");
+                            &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && (asObject(distinguishingArg)->inherits<JSDOMWindowProxy>(vm) || asObject(distinguishingArg)->inherits<JSRemoteDOMWindow>(vm))");
                         } else {
                             &$generateOverloadCallIfNecessary($overload, "distinguishingArg.isObject() && asObject(distinguishingArg)->inherits<JS" . $subtype->name . ">(vm)");
                         }
@@ -4209,7 +4212,7 @@ sub GenerateImplementation
     push(@implContent, ", CREATE_METHOD_TABLE($className) };\n\n");
 
     # Constructor
-    if ($interfaceName eq "DOMWindow") {
+    if ($interfaceName eq "DOMWindow" || $interfaceName eq "RemoteDOMWindow") {
         AddIncludesForImplementationTypeInImpl("JSDOMWindowProxy");
         push(@implContent, "${className}::$className(VM& vm, Structure* structure, Ref<$implType>&& impl, JSDOMWindowProxy* proxy)\n");
         push(@implContent, "    : $parentClassName(vm, structure, WTFMove(impl), proxy)\n");
@@ -4232,7 +4235,7 @@ sub GenerateImplementation
     }
 
     # Finish Creation
-    if ($interfaceName eq "DOMWindow") {
+    if ($interfaceName eq "DOMWindow" || $interfaceName eq "RemoteDOMWindow") {
         push(@implContent, "void ${className}::finishCreation(VM& vm, JSDOMWindowProxy* proxy)\n");
         push(@implContent, "{\n");
         push(@implContent, "    Base::finishCreation(vm, proxy);\n\n");
diff --git a/Source/WebCore/page/RemoteDOMWindow.idl b/Source/WebCore/page/RemoteDOMWindow.idl
new file mode 100644 (file)
index 0000000..2242689
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+[
+    CustomDefineOwnProperty,
+    CustomDeleteProperty,
+    CustomGetOwnPropertyNames,
+    CustomGetOwnPropertySlot,
+    CustomGetPrototype,
+    CustomPreventExtensions,
+    CustomProxyToJSObject,
+    CustomPut,
+    CustomToStringName,
+    ImplicitThis,
+    InterfaceName=Window,
+    IsImmutablePrototypeExoticObject,
+    IsImmutablePrototypeExoticObjectOnPrototype,
+    JSCustomToNativeObject,
+    JSLegacyParent=JSRemoteDOMWindowBase,
+    LegacyUnenumerableNamedProperties,
+    NoInterfaceObject,
+    PrimaryGlobal,
+] interface RemoteDOMWindow {
+    [Unforgeable, ImplementedAs=self] readonly attribute RemoteDOMWindow window;
+    [Replaceable] readonly attribute RemoteDOMWindow self;
+    [PutForwards=href, Unforgeable] readonly attribute Location? location; // FIXME: Should not be nullable.
+    [CallWith=IncumbentDocument, ForwardDeclareInHeader] void close();
+    [ForwardDeclareInHeader] readonly attribute boolean closed;
+    [CallWith=IncumbentWindow, ForwardDeclareInHeader] void focus();
+    [ForwardDeclareInHeader] void blur();
+    [Replaceable, ImplementedAs=self] readonly attribute RemoteDOMWindow frames;
+    [Replaceable] readonly attribute unsigned long length;
+    [Unforgeable] readonly attribute DOMWindow? top;
+    readonly attribute DOMWindow? opener;
+    [Replaceable] readonly attribute DOMWindow? parent;
+    [CallWith=ScriptState&IncumbentWindow, ForwardDeclareInHeader, MayThrowException] void postMessage(any message, USVString targetOrigin, optional sequence<object> transfer = []);
+};
index d845795..1a4c29b 100644 (file)
@@ -92,3 +92,11 @@ DOMAbstractView *kit(WebCore::DOMWindow* value)
     addDOMWrapper(wrapper, frame);
     return [wrapper autorelease];
 }
+
+DOMAbstractView *kit(WebCore::AbstractDOMWindow* value)
+{
+    if (!is<WebCore::DOMWindow>(value))
+        return nil;
+
+    return kit(downcast<WebCore::DOMWindow>(value));
+}
index c8a8ff4..c4d7325 100644 (file)
 #import <WebKitLegacy/DOMAbstractView.h>
 
 namespace WebCore {
+class AbstractDOMWindow;
 class DOMWindow;
 }
 
 WebCore::DOMWindow* core(DOMAbstractView *);
 DOMAbstractView *kit(WebCore::DOMWindow*);
+DOMAbstractView *kit(WebCore::AbstractDOMWindow*);
 
 @interface DOMAbstractView (WebKitLegacyInternal)
 - (void)_disconnectFrame;
index 59a1cf1..b6b7957 100644 (file)
@@ -2093,7 +2093,10 @@ static WebFrameLoadType toWebFrameLoadType(FrameLoadType frameLoadType)
     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
     JSC::VM& vm = *globalObjectObj->vm();
     if (!strcmp(globalObjectObj->classInfo(vm)->className, "JSDOMWindowProxy"))
-        anyWorldGlobalObject = static_cast<JSDOMWindowProxy*>(globalObjectObj)->window();
+        anyWorldGlobalObject = JSC::jsDynamicCast<JSDOMWindow*>(vm, static_cast<JSDOMWindowProxy*>(globalObjectObj)->window());
+
+    if (!anyWorldGlobalObject)
+        return @"";
 
     // Get the frame frome the global object we've settled on.
     Frame* frame = anyWorldGlobalObject->wrapped().frame();
index 04e44f8..682ad01 100644 (file)
@@ -2002,8 +2002,12 @@ HRESULT WebFrame::stringByEvaluatingJavaScriptInScriptWorld(IWebScriptWorld* iWo
 
     // The global object is probably a proxy object? - if so, we know how to use this!
     JSC::JSObject* globalObjectObj = toJS(globalObjectRef);
-    if (globalObjectObj->inherits<JSDOMWindowProxy>(*globalObjectObj->vm()))
-        anyWorldGlobalObject = static_cast<JSDOMWindowProxy*>(globalObjectObj)->window();
+    auto& vm = *globalObjectObj->vm();
+    if (globalObjectObj->inherits<JSDOMWindowProxy>(vm))
+        anyWorldGlobalObject = JSC::jsDynamicCast<JSDOMWindow*>(vm, static_cast<JSDOMWindowProxy*>(globalObjectObj)->window());
+
+    if (!anyWorldGlobalObject)
+        return E_INVALIDARG;
 
     // Get the frame frome the global object we've settled on.
     Frame* frame = anyWorldGlobalObject->wrapped().frame();