servo: Merge #11214 - Support WindowProxy return values in bindings (from farodin91:windowproxy); r=jdm
authorJansen Jan <farodin91@sek-server.de>
Fri, 10 Jun 2016 10:53:35 -0500
changeset 339061 8387e649f303bdcd0e5aef03b212813d7199c0eb
parent 339060 1e9fee765f5fbe2a974fedc607bfbd42b6c5018e
child 339062 733e6072944f9a7c8e18aa00177686d165621c30
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
servo: Merge #11214 - Support WindowProxy return values in bindings (from farodin91:windowproxy); r=jdm Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy --faster` does not report any errors - [x] These changes fix #10965 (github issue number if applicable). Either: - [ ] There are tests for these changes OR - [ ] These changes do not require tests because _____ Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. Source-Repo: https://github.com/servo/servo Source-Revision: 08a55e29511a2b26b7ae26ebb0b9271f80e2a7bd
servo/components/script/dom/bindings/codegen/Bindings.conf
servo/components/script/dom/bindings/codegen/CodegenRust.py
servo/components/script/dom/bindings/codegen/Configuration.py
servo/components/script/dom/htmliframeelement.rs
servo/components/script/dom/webidls/BrowserElement.webidl
servo/components/script/dom/webidls/HTMLIFrameElement.webidl
servo/components/script/dom/webidls/Window.webidl
servo/components/script/dom/window.rs
servo/components/script/webdriver_handlers.rs
--- a/servo/components/script/dom/bindings/codegen/Bindings.conf
+++ b/servo/components/script/dom/bindings/codegen/Bindings.conf
@@ -18,11 +18,17 @@ DOMInterfaces = {
 	'weakReferenceable': True,
 },
 
 #FIXME(jdm): This should be 'register': False, but then we don't generate enum types
 'TestBinding': {},
 
 'URL': {
     'weakReferenceable': True,
+},
+
+'WindowProxy' : {
+    'nativeType': 'BrowsingContext',
+    'path': 'dom::browsingcontext::BrowsingContext',
+    'register': False,
 }
 
 }
--- a/servo/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/servo/components/script/dom/bindings/codegen/CodegenRust.py
@@ -1690,17 +1690,17 @@ class CGWrapper(CGThing):
                 defn.replace("\n", "\n" + (" " * len(self.pre))))
         return self.pre + defn + self.post
 
 
 class CGImports(CGWrapper):
     """
     Generates the appropriate import/use statements.
     """
-    def __init__(self, child, descriptors, callbacks, imports, ignored_warnings=None):
+    def __init__(self, child, descriptors, callbacks, imports, config, ignored_warnings=None):
         """
         Adds a set of imports.
         """
         if ignored_warnings is None:
             ignored_warnings = [
                 'non_camel_case_types',
                 'non_upper_case_globals',
                 'unused_imports',
@@ -1751,17 +1751,21 @@ class CGImports(CGWrapper):
                 if m.isMethod():
                     types += relatedTypesForSignatures(m)
                 elif m.isAttr():
                     types += componentTypes(m.type)
 
         for c in callbacks:
             types += relatedTypesForSignatures(c)
 
-        imports += ['dom::types::%s' % getIdentifier(t).name for t in types if isImportable(t)]
+        descriptorProvider = config.getDescriptorProvider()
+        for t in types:
+            if isImportable(t):
+                descriptor = descriptorProvider.getDescriptor(getIdentifier(t).name)
+                imports += ['%s' % descriptor.path]
 
         statements = []
         if len(ignored_warnings) > 0:
             statements.append('#![allow(%s)]' % ','.join(ignored_warnings))
         statements.extend('use %s;' % i for i in sorted(set(imports)))
 
         CGWrapper.__init__(self, child,
                            pre='\n'.join(statements) + '\n\n')
@@ -2085,17 +2089,17 @@ def UnionTypes(descriptors, dictionaries
             unionStructs[name] = CGList([
                 CGUnionStruct(t, provider),
                 CGUnionConversionStruct(t, provider)
             ])
 
     # Sort unionStructs by key, retrieve value
     unionStructs = (i[1] for i in sorted(unionStructs.items(), key=operator.itemgetter(0)))
 
-    return CGImports(CGList(unionStructs, "\n\n"), [], [], imports, ignored_warnings=[])
+    return CGImports(CGList(unionStructs, "\n\n"), [], [], imports, config, ignored_warnings=[])
 
 
 class Argument():
     """
     A class for outputting the type and name of an argument
     """
     def __init__(self, argType, name, default=None, mutable=False):
         self.argType = argType
@@ -5455,17 +5459,18 @@ class CGBindingRoot(CGThing):
         descriptors = config.getDescriptors(webIDLFile=webIDLFile,
                                             hasInterfaceObject=True)
         # We also want descriptors that have an interface prototype object
         # (isCallback=False), but we don't want to include a second copy
         # of descriptors that we also matched in the previous line
         # (hence hasInterfaceObject=False).
         descriptors.extend(config.getDescriptors(webIDLFile=webIDLFile,
                                                  hasInterfaceObject=False,
-                                                 isCallback=False))
+                                                 isCallback=False,
+                                                 register=True))
 
         dictionaries = config.getDictionaries(webIDLFile=webIDLFile)
 
         mainCallbacks = config.getCallbacks(webIDLFile=webIDLFile)
         callbackDescriptors = config.getDescriptors(webIDLFile=webIDLFile,
                                                     isCallback=True)
 
         enums = config.getEnums(webIDLFile)
@@ -5583,31 +5588,32 @@ class CGBindingRoot(CGThing):
             'dom::bindings::guard::{Condition, Guard}',
             'dom::bindings::proxyhandler',
             'dom::bindings::proxyhandler::{ensure_expando_object, fill_property_descriptor}',
             'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}',
             'dom::bindings::num::Finite',
             'dom::bindings::str::{ByteString, DOMString, USVString}',
             'dom::bindings::trace::RootedVec',
             'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
+            'dom::browsingcontext::BrowsingContext',
             'mem::heap_size_of_raw_self_and_children',
             'libc',
             'util::prefs',
             'std::borrow::ToOwned',
             'std::cmp',
             'std::mem',
             'std::num',
             'std::os',
             'std::ptr',
             'std::str',
             'std::rc',
             'std::rc::Rc',
             'std::default::Default',
             'std::ffi::CString',
-        ])
+        ], config)
 
         # Add the auto-generated comment.
         curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
 
         # Store the final result.
         self.root = curr
 
     def define(self):
@@ -6273,17 +6279,17 @@ class GlobalGenRoots():
         code = CGList([
             CGRegisterProxyHandlers(config),
         ], "\n")
 
         return CGImports(code, [], [], [
             'dom::bindings::codegen',
             'dom::bindings::codegen::PrototypeList::Proxies',
             'libc',
-        ], ignored_warnings=[])
+        ], config, ignored_warnings=[])
 
     @staticmethod
     def InterfaceTypes(config):
         descriptors = [d.name for d in config.getDescriptors(register=True, isCallback=False)]
         curr = CGList([CGGeneric("pub use dom::%s::%s;\n" % (name.lower(), name)) for name in descriptors])
         curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT)
         return curr
 
--- a/servo/components/script/dom/bindings/codegen/Configuration.py
+++ b/servo/components/script/dom/bindings/codegen/Configuration.py
@@ -168,33 +168,35 @@ class Descriptor(DescriptorProvider):
         if not self.isExposedConditionally():
             if interface.parent and interface.parent.isExposedConditionally():
                 raise TypeError("%s is not conditionally exposed but inherits from "
                                 "%s which is" %
                                 (interface.identifier.name, interface.parent.identifier.name))
 
         # Read the desc, and fill in the relevant defaults.
         ifaceName = self.interface.identifier.name
+        typeName = desc.get('nativeType', ifaceName)
 
         # Callback types do not use JS smart pointers, so we should not use the
         # built-in rooting mechanisms for them.
         if self.interface.isCallback():
             self.needsRooting = False
             ty = "%sBinding::%s" % (ifaceName, ifaceName)
             self.returnType = "Rc<%s>" % ty
             self.argumentType = "???"
             self.nativeType = ty
         else:
             self.needsRooting = True
-            self.returnType = "Root<%s>" % ifaceName
-            self.argumentType = "&%s" % ifaceName
-            self.nativeType = "*const %s" % ifaceName
+            self.returnType = "Root<%s>" % typeName
+            self.argumentType = "&%s" % typeName
+            self.nativeType = "*const %s" % typeName
 
-        self.concreteType = ifaceName
+        self.concreteType = typeName
         self.register = desc.get('register', True)
+        self.path = desc.get('path', 'dom::types::%s' % typeName)
         self.outerObjectHook = desc.get('outerObjectHook', 'None')
         self.proxy = False
         self.weakReferenceable = desc.get('weakReferenceable', False)
 
         # If we're concrete, we need to crawl our ancestor interfaces and mark
         # them as having a concrete descendant.
         self.concrete = (not self.interface.isCallback() and
                          not self.interface.getExtendedAttribute("Abstract"))
--- a/servo/components/script/dom/htmliframeelement.rs
+++ b/servo/components/script/dom/htmliframeelement.rs
@@ -17,16 +17,17 @@ use dom::bindings::codegen::Bindings::HT
 use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
 use dom::bindings::conversions::ToJSValConvertible;
 use dom::bindings::error::{Error, ErrorResult};
 use dom::bindings::global::GlobalRef;
 use dom::bindings::inheritance::Castable;
 use dom::bindings::js::{Root, LayoutJS};
 use dom::bindings::reflector::Reflectable;
 use dom::bindings::str::DOMString;
+use dom::browsingcontext::BrowsingContext;
 use dom::customevent::CustomEvent;
 use dom::document::Document;
 use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers};
 use dom::event::Event;
 use dom::eventtarget::EventTarget;
 use dom::htmlelement::HTMLElement;
 use dom::node::{Node, NodeDamage, UnbindContext, window_from_node, document_from_node};
 use dom::urlhelper::UrlHelper;
@@ -251,16 +252,25 @@ impl HTMLIFrameElement {
         if self.Mozbrowser() {
             let element = self.upcast::<Element>();
             element.has_attribute(&Atom::from("mozprivatebrowsing"))
         } else {
             false
         }
     }
 
+    pub fn get_content_window(&self) -> Option<Root<Window>> {
+        self.subpage_id.get().and_then(|subpage_id| {
+            let window = window_from_node(self);
+            let window = window.r();
+            let browsing_context = window.browsing_context();
+            browsing_context.find_child_by_subpage(subpage_id)
+        })
+    }
+
 }
 
 pub trait HTMLIFrameElementLayoutMethods {
     fn pipeline_id(self) -> Option<PipelineId>;
     fn get_width(&self) -> LengthOrPercentageOrAuto;
     fn get_height(&self) -> LengthOrPercentageOrAuto;
 }
 
@@ -417,28 +427,26 @@ impl HTMLIFrameElementMethods for HTMLIF
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-iframe-sandbox
     fn SetSandbox(&self, sandbox: DOMString) {
         self.upcast::<Element>().set_tokenlist_attribute(&atom!("sandbox"), sandbox);
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-iframe-contentwindow
-    fn GetContentWindow(&self) -> Option<Root<Window>> {
-        self.subpage_id.get().and_then(|subpage_id| {
-            let window = window_from_node(self);
-            let window = window.r();
-            let browsing_context = window.browsing_context();
-            browsing_context.find_child_by_subpage(subpage_id)
-        })
+    fn GetContentWindow(&self) -> Option<Root<BrowsingContext>> {
+        match self.get_content_window() {
+            Some(ref window) => Some(window.browsing_context()),
+            None => None
+        }
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-iframe-contentdocument
     fn GetContentDocument(&self) -> Option<Root<Document>> {
-        self.GetContentWindow().and_then(|window| {
+        self.get_content_window().and_then(|window| {
             // FIXME(#10964): this should use the Document's origin and the
             //                origin of the incumbent settings object.
             let self_url = self.get_url();
             let win_url = window_from_node(self).get_url();
 
             if UrlHelper::SameOrigin(&self_url, &win_url) {
                 Some(window.Document())
             } else {
--- a/servo/components/script/dom/webidls/BrowserElement.webidl
+++ b/servo/components/script/dom/webidls/BrowserElement.webidl
@@ -154,26 +154,26 @@ interface BrowserElementPrivileged {
   //                    sequence<long> y,
   //                    sequence<unsigned long> rx,
   //                    sequence<unsigned long> ry,
   //                    sequence<float> rotationAngles,
   //                    sequence<float> forces,
   //                    unsigned long count,
   //                    unsigned long modifiers);
 
-  [Func="Window::global_is_mozbrowser", Throws]
+  [Func="::dom::window::Window::global_is_mozbrowser", Throws]
   void goBack();
 
-  [Func="Window::global_is_mozbrowser", Throws]
+  [Func="::dom::window::Window::global_is_mozbrowser", Throws]
   void goForward();
 
-  [Func="Window::global_is_mozbrowser", Throws]
+  [Func="::dom::window::Window::global_is_mozbrowser", Throws]
   void reload(optional boolean hardReload = false);
 
-  [Func="Window::global_is_mozbrowser", Throws]
+  [Func="::dom::window::Window::global_is_mozbrowser", Throws]
   void stop();
 
   //[Throws,
   // Pref="dom.mozBrowserFramesEnabled",
   // CheckAnyPermissions="browser"]
   //DOMRequest download(DOMString url,
   //                    optional BrowserElementDownloadOptions options);
 
--- a/servo/components/script/dom/webidls/HTMLIFrameElement.webidl
+++ b/servo/components/script/dom/webidls/HTMLIFrameElement.webidl
@@ -8,31 +8,30 @@ interface HTMLIFrameElement : HTMLElemen
   //         attribute DOMString srcdoc;
   //         attribute DOMString name;
            attribute DOMString sandbox;
   //         attribute boolean seamless;
   //         attribute boolean allowFullscreen;
            attribute DOMString width;
            attribute DOMString height;
   readonly attribute Document? contentDocument;
-  //readonly attribute WindowProxy? contentWindow;
-  readonly attribute Window? contentWindow;
+  readonly attribute WindowProxy? contentWindow;
 
   // also has obsolete members
 };
 
 // https://html.spec.whatwg.org/multipage/#HTMLIFrameElement-partial
 partial interface HTMLIFrameElement {
   //         attribute DOMString align;
   //         attribute DOMString scrolling;
   //         attribute DOMString frameBorder;
   //         attribute DOMString longDesc;
 
   //[TreatNullAs=EmptyString] attribute DOMString marginHeight;
   //[TreatNullAs=EmptyString] attribute DOMString marginWidth;
 };
 
 partial interface HTMLIFrameElement {
-    [Func="Window::global_is_mozbrowser"]
+    [Func="::dom::window::Window::global_is_mozbrowser"]
     attribute boolean mozbrowser;
 };
 
 HTMLIFrameElement implements BrowserElement;
--- a/servo/components/script/dom/webidls/Window.webidl
+++ b/servo/components/script/dom/webidls/Window.webidl
@@ -1,20 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // https://html.spec.whatwg.org/multipage/#window
 [PrimaryGlobal]
 /*sealed*/ interface Window : EventTarget {
   // the current browsing context
-  //[Unforgeable] readonly attribute WindowProxy window;
-  //[Replaceable] readonly attribute WindowProxy self;
-  readonly attribute Window window;
-  [BinaryName="Self_"] readonly attribute Window self;
+  [Unforgeable] readonly attribute WindowProxy window;
+  [BinaryName="Self_", Replaceable] readonly attribute WindowProxy self;
   [Unforgeable] readonly attribute Document document;
   //         attribute DOMString name;
   [/*PutForwards=href, */Unforgeable] readonly attribute Location location;
   //readonly attribute History history;
   //[Replaceable] readonly attribute BarProp locationbar;
   //[Replaceable] readonly attribute BarProp menubar;
   //[Replaceable] readonly attribute BarProp personalbar;
   //[Replaceable] readonly attribute BarProp scrollbars;
@@ -23,24 +21,21 @@
   attribute DOMString status;
   void close();
   //readonly attribute boolean closed;
   //void stop();
   //void focus();
   //void blur();
 
   // other browsing contexts
-  //[Replaceable] readonly attribute WindowProxy frames;
-  readonly attribute Window frames;
+  [Replaceable] readonly attribute WindowProxy frames;
   //[Replaceable] readonly attribute unsigned long length;
-  //[Unforgeable] readonly attribute WindowProxy top;
-  readonly attribute Window top;
+  [Unforgeable] readonly attribute WindowProxy top;
   //         attribute any opener;
-  //readonly attribute WindowProxy parent;
-  readonly attribute Window parent;
+  readonly attribute WindowProxy parent;
   readonly attribute Element? frameElement;
   //WindowProxy open(optional DOMString url = "about:blank", optional DOMString target = "_blank",
   //                 optional DOMString features = "", optional boolean replace = false);
   //getter WindowProxy (unsigned long index);
   //getter object (DOMString name);
 
   // the user agent
   readonly attribute Navigator navigator;
@@ -60,16 +55,19 @@
 
   //void postMessage(any message, DOMString targetOrigin, optional sequence<Transferable> transfer);
 
   // also has obsolete members
 };
 Window implements GlobalEventHandlers;
 Window implements WindowEventHandlers;
 
+[NoInterfaceObject]
+interface WindowProxy {};
+
 // https://html.spec.whatwg.org/multipage/#timers
 [NoInterfaceObject/*, Exposed=Window,Worker*/]
 interface WindowTimers {
   long setTimeout(Function handler, optional long timeout = 0, any... arguments);
   long setTimeout(DOMString handler, optional long timeout = 0, any... arguments);
   void clearTimeout(optional long handle = 0);
   long setInterval(Function handler, optional long timeout = 0, any... arguments);
   long setInterval(DOMString handler, optional long timeout = 0, any... arguments);
--- a/servo/components/script/dom/window.rs
+++ b/servo/components/script/dom/window.rs
@@ -553,42 +553,45 @@ impl WindowMethods for Window {
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-windowtimers-clearinterval
     fn ClearInterval(&self, handle: i32) {
         self.ClearTimeout(handle);
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-window
-    fn Window(&self) -> Root<Window> {
-        Root::from_ref(self)
+    fn Window(&self) -> Root<BrowsingContext> {
+        self.browsing_context()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-self
-    fn Self_(&self) -> Root<Window> {
-        self.Window()
+    fn Self_(&self) -> Root<BrowsingContext> {
+        self.browsing_context()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-frames
-    fn Frames(&self) -> Root<Window> {
-        self.Window()
+    fn Frames(&self) -> Root<BrowsingContext> {
+        self.browsing_context()
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-parent
-    fn Parent(&self) -> Root<Window> {
-        self.parent().unwrap_or(self.Window())
+    fn Parent(&self) -> Root<BrowsingContext> {
+        match  self.parent() {
+            Some(window) => window.browsing_context(),
+            None => self.Window()
+        }
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-top
-    fn Top(&self) -> Root<Window> {
-        let mut window = self.Window();
+    fn Top(&self) -> Root<BrowsingContext> {
+        let mut window = Root::from_ref(self);
         while let Some(parent) = window.parent() {
             window = parent;
         }
-        window
+        window.browsing_context()
     }
 
     // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/
     // NavigationTiming/Overview.html#sec-window.performance-attribute
     fn Performance(&self) -> Root<Performance> {
         self.performance.or_init(|| {
             Performance::new(self, self.navigation_start,
                              self.navigation_start_precise)
--- a/servo/components/script/webdriver_handlers.rs
+++ b/servo/components/script/webdriver_handlers.rs
@@ -1,17 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
 use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
 use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
 use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
-use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
 use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
 use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods;
 use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
 use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods;
 use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
 use dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior};
 use dom::bindings::inheritance::Castable;
 use dom::bindings::js::Root;
@@ -100,17 +99,17 @@ pub fn handle_get_frame_id(context: &Bro
         WebDriverFrameId::Short(_) => {
             // This isn't supported yet
             Ok(None)
         },
         WebDriverFrameId::Element(x) => {
             match find_node_by_unique_id(context, pipeline, x) {
                 Some(ref node) => {
                     match node.downcast::<HTMLIFrameElement>() {
-                        Some(ref elem) => Ok(elem.GetContentWindow()),
+                        Some(ref elem) => Ok(elem.get_content_window()),
                         None => Err(())
                     }
                 },
                 None => Err(())
             }
         },
         WebDriverFrameId::Parent => {
             let window = context.active_window();