v8binding: Support mixture of [SecureContext] and inherited interface member

Inherited IDL interface member shouldn't be affected by
[SecureContext] applied on an inheriting IDL interface.  This patch
fixes it.

Example

    interface Base {
      [Unforgeable] attribute T attr;
    };

    [SecureContext]
    interface Derived : Base {
      attribute T attr2;
    };

When an instance of |Derived| is created in non-secure context,
the instance does not have |attr2| due to [SecureContext], however,
the instance must have |attr| because Base's attr is not specified
with [SecureContext] although |attr| is inherited to Derived.

Bug: 933731
Change-Id: I1ffb8acb0ead8d6e378c6f51a131b5779ddd293c
Reviewed-on: https://chromium-review.googlesource.com/c/1478668
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Reviewed-by: Hitoshi Yoshida <peria@chromium.org>
Cr-Commit-Position: refs/heads/master@{#634122}
diff --git a/third_party/blink/renderer/bindings/scripts/idl_definitions.py b/third_party/blink/renderer/bindings/scripts/idl_definitions.py
index 27073618..08096cf3 100644
--- a/third_party/blink/renderer/bindings/scripts/idl_definitions.py
+++ b/third_party/blink/renderer/bindings/scripts/idl_definitions.py
@@ -429,6 +429,9 @@
         self.name = node.GetName() if node else None
         self.idl_type = None
         self.extended_attributes = {}
+        # In what interface the attribute is (originally) defined when the
+        # attribute is inherited from an ancestor interface.
+        self.defined_in = None
 
         if node:
             children = node.GetChildren()
@@ -469,6 +472,9 @@
         # we don't use the full type_node_to_type function.
         self.idl_type = type_node_inner_to_type(type_node)
         self.value = value_node.GetProperty('VALUE')
+        # In what interface the attribute is (originally) defined when the
+        # attribute is inherited from an ancestor interface.
+        self.defined_in = None
 
         if num_children == 3:
             ext_attributes_node = children[2]
@@ -545,6 +551,9 @@
         self.is_constructor = False
         self.idl_type = None
         self.is_static = False
+        # In what interface the attribute is (originally) defined when the
+        # attribute is inherited from an ancestor interface.
+        self.defined_in = None
 
         if not node:
             return
diff --git a/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py b/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
index a27af07..3870250 100644
--- a/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
+++ b/third_party/blink/renderer/bindings/scripts/interface_dependency_resolver.py
@@ -334,6 +334,9 @@
         interface = interfaces_info[interface_name]
         unforgeable_attributes, referenced_interfaces, cpp_includes = collect_unforgeable_attributes_in_ancestors(interface.get('parent'), component)
         this_unforgeable = interface.get('unforgeable_attributes', [])
+        for attr in this_unforgeable:
+            if attr.defined_in is None:
+                attr.defined_in = interface_name
         unforgeable_attributes.extend(this_unforgeable)
         this_referenced = [attr.idl_type.base_type for attr in this_unforgeable
                            if attr.idl_type.base_type in
diff --git a/third_party/blink/renderer/bindings/scripts/scripts.gni b/third_party/blink/renderer/bindings/scripts/scripts.gni
index 4e5f888..5cbe0058 100644
--- a/third_party/blink/renderer/bindings/scripts/scripts.gni
+++ b/third_party/blink/renderer/bindings/scripts/scripts.gni
@@ -93,7 +93,8 @@
       visibility = invoker.visibility
     }
 
-    inputs = [ "$bindings_scripts_dir/utilities.py" ] + invoker.sources
+    inputs = [ "$bindings_scripts_dir/utilities.py" ] + idl_compiler_files +
+             invoker.sources
     outputs = [
       invoker.interfaces_info_file,
       invoker.component_info_file,
diff --git a/third_party/blink/renderer/bindings/scripts/v8_utilities.py b/third_party/blink/renderer/bindings/scripts/v8_utilities.py
index 9bf5886..4db3d6e 100644
--- a/third_party/blink/renderer/bindings/scripts/v8_utilities.py
+++ b/third_party/blink/renderer/bindings/scripts/v8_utilities.py
@@ -348,14 +348,27 @@
     """Returns C++ code that checks whether an interface/method/attribute/etc. is exposed
     to the current context. Requires that the surrounding code defines an |is_secure_context|
     variable prior to this check."""
-    if 'SecureContext' in member.extended_attributes or 'SecureContext' in interface.extended_attributes:
-        conditions = ['is_secure_context']
-        if 'SecureContext' in member.extended_attributes and member.extended_attributes['SecureContext'] is not None:
-            conditions.append('!%s' % runtime_enabled_function(member.extended_attributes['SecureContext']))
-        if 'SecureContext' in interface.extended_attributes and interface.extended_attributes['SecureContext'] is not None:
-            conditions.append('!%s' % runtime_enabled_function(interface.extended_attributes['SecureContext']))
-        return ' || '.join(conditions)
-    return None
+    member_is_secure_context = 'SecureContext' in member.extended_attributes
+    interface_is_secure_context = ((member.defined_in is None or
+                                    member.defined_in == interface.name) and
+                                   'SecureContext' in interface.extended_attributes)
+
+    if not (member_is_secure_context or interface_is_secure_context):
+        return None
+
+    conditions = ['is_secure_context']
+
+    if member_is_secure_context:
+        conditional = member.extended_attributes['SecureContext']
+        if conditional:
+            conditions.append('!{}'.format(runtime_enabled_function(conditional)))
+
+    if interface_is_secure_context:
+        conditional = interface.extended_attributes['SecureContext']
+        if conditional:
+            conditions.append('!{}'.format(runtime_enabled_function(conditional)))
+
+    return ' || '.join(conditions)
 
 
 # [ImplementedAs]