Merge mozilla-central to autoland. a=merge CLOSED TREE
authorNarcis Beleuzu <nbeleuzu@mozilla.com>
Fri, 10 May 2019 01:17:29 +0300
changeset 532127 1d1443055d8f09ad6fe8170c714705167ef34d94
parent 532126 b35cf8000e7a708377696f3859ae6bfa0fa8f554 (current diff)
parent 532050 f28f80e2466839e5b50c9b9f728988044fecb186 (diff)
child 532128 e28c51cc8100164c7817a8516b110af91d5b8da7
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland. a=merge CLOSED TREE
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,5 +1,5 @@
 This is the PDF.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 2.2.160
+Current extension version is: 2.2.167
 
-Taken from upstream commit: 155304a0
+Taken from upstream commit: ca2fee3d
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-var pdfjsVersion = '2.2.160';
-var pdfjsBuild = '155304a0';
+var pdfjsVersion = '2.2.167';
+var pdfjsBuild = 'ca2fee3d';
 
 var pdfjsSharedUtil = __w_pdfjs_require__(1);
 
 var pdfjsDisplayAPI = __w_pdfjs_require__(6);
 
 var pdfjsDisplayTextLayer = __w_pdfjs_require__(18);
 
 var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(19);
@@ -170,16 +170,17 @@ exports.shadow = pdfjsSharedUtil.shadow;
 exports.Util = pdfjsSharedUtil.Util;
 exports.ReadableStream = pdfjsSharedUtil.ReadableStream;
 exports.URL = pdfjsSharedUtil.URL;
 exports.RenderingCancelledException = pdfjsDisplayDisplayUtils.RenderingCancelledException;
 exports.getFilenameFromUrl = pdfjsDisplayDisplayUtils.getFilenameFromUrl;
 exports.LinkTarget = pdfjsDisplayDisplayUtils.LinkTarget;
 exports.addLinkAttributes = pdfjsDisplayDisplayUtils.addLinkAttributes;
 exports.loadScript = pdfjsDisplayDisplayUtils.loadScript;
+exports.PDFDateString = pdfjsDisplayDisplayUtils.PDFDateString;
 exports.GlobalWorkerOptions = pdfjsDisplayWorkerOptions.GlobalWorkerOptions;
 exports.apiCompatibilityParams = pdfjsDisplayAPICompatibility.apiCompatibilityParams;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
@@ -1298,17 +1299,17 @@ function _fetchDocument(worker, source, 
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
     source.progressiveDone = pdfDataRangeTransport.progressiveDone;
   }
 
   return worker.messageHandler.sendWithPromise('GetDocRequest', {
     docId,
-    apiVersion: '2.2.160',
+    apiVersion: '2.2.167',
     source: {
       data: source.data,
       url: source.url,
       password: source.password,
       disableAutoFetch: source.disableAutoFetch,
       rangeChunkSize: source.rangeChunkSize,
       length: source.length
     },
@@ -3092,19 +3093,19 @@ const InternalRenderTask = function Inte
       }
     }
 
   }
 
   return InternalRenderTask;
 }();
 
-const version = '2.2.160';
+const version = '2.2.167';
 exports.version = version;
-const build = '155304a0';
+const build = 'ca2fee3d';
 exports.build = build;
 
 /***/ }),
 /* 7 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
@@ -3114,17 +3115,17 @@ Object.defineProperty(exports, "__esModu
 });
 exports.addLinkAttributes = addLinkAttributes;
 exports.getFilenameFromUrl = getFilenameFromUrl;
 exports.isFetchSupported = isFetchSupported;
 exports.isValidFetchUrl = isValidFetchUrl;
 exports.loadScript = loadScript;
 exports.deprecated = deprecated;
 exports.releaseImageResources = releaseImageResources;
-exports.DummyStatTimer = exports.StatTimer = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.LinkTarget = exports.RenderingCancelledException = exports.PageViewport = void 0;
+exports.PDFDateString = exports.DummyStatTimer = exports.StatTimer = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.LinkTarget = exports.RenderingCancelledException = exports.PageViewport = void 0;
 
 var _util = __w_pdfjs_require__(1);
 
 const DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
 exports.DEFAULT_LINK_REL = DEFAULT_LINK_REL;
 const SVG_NS = 'http://www.w3.org/2000/svg';
 
 class DOMCanvasFactory {
@@ -3511,16 +3512,66 @@ function releaseImageResources(img) {
 
   if (typeof url === 'string' && url.startsWith('blob:') && _util.URL.revokeObjectURL) {
     _util.URL.revokeObjectURL(url);
   }
 
   img.removeAttribute('src');
 }
 
+let pdfDateStringRegex;
+
+class PDFDateString {
+  static toDateObject(input) {
+    if (!input || !(0, _util.isString)(input)) {
+      return null;
+    }
+
+    if (!pdfDateStringRegex) {
+      pdfDateStringRegex = new RegExp('^D:' + '(\\d{4})' + '(\\d{2})?' + '(\\d{2})?' + '(\\d{2})?' + '(\\d{2})?' + '(\\d{2})?' + '([Z|+|-])?' + '(\\d{2})?' + '\'?' + '(\\d{2})?' + '\'?');
+    }
+
+    const matches = pdfDateStringRegex.exec(input);
+
+    if (!matches) {
+      return null;
+    }
+
+    const year = parseInt(matches[1], 10);
+    let month = parseInt(matches[2], 10);
+    month = month >= 1 && month <= 12 ? month - 1 : 0;
+    let day = parseInt(matches[3], 10);
+    day = day >= 1 && day <= 31 ? day : 1;
+    let hour = parseInt(matches[4], 10);
+    hour = hour >= 0 && hour <= 23 ? hour : 0;
+    let minute = parseInt(matches[5], 10);
+    minute = minute >= 0 && minute <= 59 ? minute : 0;
+    let second = parseInt(matches[6], 10);
+    second = second >= 0 && second <= 59 ? second : 0;
+    const universalTimeRelation = matches[7] || 'Z';
+    let offsetHour = parseInt(matches[8], 10);
+    offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0;
+    let offsetMinute = parseInt(matches[9], 10) || 0;
+    offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0;
+
+    if (universalTimeRelation === '-') {
+      hour += offsetHour;
+      minute += offsetMinute;
+    } else if (universalTimeRelation === '+') {
+      hour -= offsetHour;
+      minute -= offsetMinute;
+    }
+
+    return new Date(Date.UTC(year, month, day, hour, minute, second));
+  }
+
+}
+
+exports.PDFDateString = PDFDateString;
+
 /***/ }),
 /* 8 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
@@ -8994,16 +9045,17 @@ class AnnotationElement {
       container.appendChild(trigger);
     }
 
     let popupElement = new PopupElement({
       container,
       trigger,
       color: data.color,
       title: data.title,
+      modificationDate: data.modificationDate,
       contents: data.contents,
       hideWrapper: true
     });
     let popup = popupElement.render();
     popup.style.left = container.style.width;
     container.appendChild(popup);
   }
 
@@ -9291,16 +9343,17 @@ class PopupAnnotationElement extends Ann
       return this.container;
     }
 
     let popup = new PopupElement({
       container: this.container,
       trigger: parentElement,
       color: this.data.color,
       title: this.data.title,
+      modificationDate: this.data.modificationDate,
       contents: this.data.contents
     });
     let parentLeft = parseFloat(parentElement.style.left);
     let parentWidth = parseFloat(parentElement.style.width);
     this.container.style.transformOrigin = -(parentLeft + parentWidth) + 'px -' + parentElement.style.top;
     this.container.style.left = parentLeft + parentWidth + 'px';
     this.container.appendChild(popup.render());
     return this.container;
@@ -9309,16 +9362,17 @@ class PopupAnnotationElement extends Ann
 }
 
 class PopupElement {
   constructor(parameters) {
     this.container = parameters.container;
     this.trigger = parameters.trigger;
     this.color = parameters.color;
     this.title = parameters.title;
+    this.modificationDate = parameters.modificationDate;
     this.contents = parameters.contents;
     this.hideWrapper = parameters.hideWrapper || false;
     this.pinned = false;
   }
 
   render() {
     const BACKGROUND_ENLIGHT = 0.7;
     let wrapper = document.createElement('div');
@@ -9331,26 +9385,40 @@ class PopupElement {
 
     if (color) {
       let r = BACKGROUND_ENLIGHT * (255 - color[0]) + color[0];
       let g = BACKGROUND_ENLIGHT * (255 - color[1]) + color[1];
       let b = BACKGROUND_ENLIGHT * (255 - color[2]) + color[2];
       popup.style.backgroundColor = _util.Util.makeCssRgb(r | 0, g | 0, b | 0);
     }
 
-    let contents = this._formatContents(this.contents);
-
     let title = document.createElement('h1');
     title.textContent = this.title;
+    popup.appendChild(title);
+
+    const dateObject = _display_utils.PDFDateString.toDateObject(this.modificationDate);
+
+    if (dateObject) {
+      const modificationDate = document.createElement('span');
+      modificationDate.textContent = '{{date}}, {{time}}';
+      modificationDate.dataset.l10nId = 'annotation_date_string';
+      modificationDate.dataset.l10nArgs = JSON.stringify({
+        date: dateObject.toLocaleDateString(),
+        time: dateObject.toLocaleTimeString()
+      });
+      popup.appendChild(modificationDate);
+    }
+
+    let contents = this._formatContents(this.contents);
+
+    popup.appendChild(contents);
     this.trigger.addEventListener('click', this._toggle.bind(this));
     this.trigger.addEventListener('mouseover', this._show.bind(this, false));
     this.trigger.addEventListener('mouseout', this._hide.bind(this, false));
     popup.addEventListener('click', this._hide.bind(this, true));
-    popup.appendChild(title);
-    popup.appendChild(contents);
     wrapper.appendChild(popup);
     return wrapper;
   }
 
   _formatContents(contents) {
     let p = document.createElement('p');
     let lines = contents.split(/(?:\r\n?|\n)/);
 
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -118,18 +118,18 @@ return /******/ (function(modules) { // 
 /************************************************************************/
 /******/ ([
 /* 0 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
-const pdfjsVersion = '2.2.160';
-const pdfjsBuild = '155304a0';
+const pdfjsVersion = '2.2.167';
+const pdfjsBuild = 'ca2fee3d';
 
 const pdfjsCoreWorker = __w_pdfjs_require__(1);
 
 exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
@@ -373,17 +373,17 @@ var WorkerMessageHandler = {
 
   createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     const verbosity = (0, _util.getVerbosityLevel)();
     let apiVersion = docParams.apiVersion;
-    let workerVersion = '2.2.160';
+    let workerVersion = '2.2.167';
 
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
 
     var docId = docParams.docId;
     var docBaseUrl = docParams.docBaseUrl;
     var workerHandlerName = docParams.docId + '_worker';
@@ -18313,27 +18313,31 @@ function getTransformMatrix(rect, bbox, 
   let xRatio = (rect[2] - rect[0]) / (maxX - minX);
   let yRatio = (rect[3] - rect[1]) / (maxY - minY);
   return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio];
 }
 
 class Annotation {
   constructor(params) {
     let dict = params.dict;
+    this.setCreationDate(dict.get('CreationDate'));
+    this.setModificationDate(dict.get('M'));
     this.setFlags(dict.get('F'));
     this.setRectangle(dict.getArray('Rect'));
     this.setColor(dict.getArray('C'));
     this.setBorderStyle(dict);
     this.setAppearance(dict);
     this.data = {
       annotationFlags: this.flags,
       borderStyle: this.borderStyle,
       color: this.color,
+      creationDate: this.creationDate,
       hasAppearance: !!this.appearance,
       id: params.id,
+      modificationDate: this.modificationDate,
       rect: this.rectangle,
       subtype: params.subtype
     };
   }
 
   _hasFlag(flags, flag) {
     return !!(flags & flag);
   }
@@ -18357,16 +18361,24 @@ class Annotation {
   get printable() {
     if (this.flags === 0) {
       return false;
     }
 
     return this._isPrintable(this.flags);
   }
 
+  setCreationDate(creationDate) {
+    this.creationDate = (0, _util.isString)(creationDate) ? creationDate : null;
+  }
+
+  setModificationDate(modificationDate) {
+    this.modificationDate = (0, _util.isString)(modificationDate) ? modificationDate : null;
+  }
+
   setFlags(flags) {
     this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0;
   }
 
   hasFlag(flag) {
     return this._hasFlag(this.flags, flag);
   }
 
@@ -18943,16 +18955,30 @@ class PopupAnnotation extends Annotation
     }
 
     let parentSubtype = parentItem.get('Subtype');
     this.data.parentType = (0, _primitives.isName)(parentSubtype) ? parentSubtype.name : null;
     this.data.parentId = dict.getRaw('Parent').toString();
     this.data.title = (0, _util.stringToPDFString)(parentItem.get('T') || '');
     this.data.contents = (0, _util.stringToPDFString)(parentItem.get('Contents') || '');
 
+    if (!parentItem.has('CreationDate')) {
+      this.data.creationDate = null;
+    } else {
+      this.setCreationDate(parentItem.get('CreationDate'));
+      this.data.creationDate = this.creationDate;
+    }
+
+    if (!parentItem.has('M')) {
+      this.data.modificationDate = null;
+    } else {
+      this.setModificationDate(parentItem.get('M'));
+      this.data.modificationDate = this.modificationDate;
+    }
+
     if (!parentItem.has('C')) {
       this.data.color = null;
     } else {
       this.setColor(parentItem.getArray('C'));
       this.data.color = this.color;
     }
 
     if (!this.viewable) {
@@ -20577,40 +20603,39 @@ var PartialEvaluator = function PartialE
         }
       } else {
         var opArgs = operatorList.argsArray[lastIndex];
         opArgs[0].push(fn);
         Array.prototype.push.apply(opArgs[1], args);
       }
     },
 
-    handleColorN: function PartialEvaluator_handleColorN(operatorList, fn, args, cs, patterns, resources, task) {
+    async handleColorN(operatorList, fn, args, cs, patterns, resources, task) {
       var patternName = args[args.length - 1];
       var pattern;
 
       if ((0, _primitives.isName)(patternName) && (pattern = patterns.get(patternName.name))) {
         var dict = (0, _primitives.isStream)(pattern) ? pattern.dict : pattern;
         var typeNum = dict.get('PatternType');
 
         if (typeNum === TILING_PATTERN) {
           var color = cs.base ? cs.base.getRgb(args, 0) : null;
           return this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task);
         } else if (typeNum === SHADING_PATTERN) {
           var shading = dict.get('Shading');
           var matrix = dict.getArray('Matrix');
           pattern = _pattern.Pattern.parseShading(shading, matrix, this.xref, resources, this.handler, this.pdfFunctionFactory);
           operatorList.addOp(fn, pattern.getIR());
-          return Promise.resolve();
-        }
-
-        return Promise.reject(new Error('Unknown PatternType: ' + typeNum));
-      }
-
-      operatorList.addOp(fn, args);
-      return Promise.resolve();
+          return undefined;
+        }
+
+        throw new _util.FormatError(`Unknown PatternType: ${typeNum}`);
+      }
+
+      throw new _util.FormatError(`Unknown PatternName: ${patternName}`);
     },
 
     getOperatorList({
       stream,
       task,
       resources,
       operatorList,
       initialState = null
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -217,35 +217,43 @@
   width: 20em;
 }
 
 .annotationLayer .popup {
   position: absolute;
   z-index: 200;
   max-width: 20em;
   background-color: #FFFF99;
-  box-shadow: 0px 2px 5px #333;
+  box-shadow: 0px 2px 5px #888;
   border-radius: 2px;
-  padding: 0.6em;
+  padding: 6px;
   margin-left: 5px;
   cursor: pointer;
   font: message-box;
+  font-size: 9px;
   word-wrap: break-word;
 }
 
+.annotationLayer .popup > * {
+  font-size: 9px;
+}
+
 .annotationLayer .popup h1 {
-  font-size: 1em;
-  border-bottom: 1px solid #000000;
-  margin: 0;
-  padding-bottom: 0.2em;
+  display: inline-block;
+}
+
+.annotationLayer .popup span {
+  display: inline-block;
+  margin-left: 5px;
 }
 
 .annotationLayer .popup p {
-  margin: 0;
-  padding-top: 0.2em;
+  border-top: 1px solid #333;
+  margin-top: 2px;
+  padding-top: 2px;
 }
 
 .annotationLayer .highlightAnnotation,
 .annotationLayer .underlineAnnotation,
 .annotationLayer .squigglyAnnotation,
 .annotationLayer .strikeoutAnnotation,
 .annotationLayer .freeTextAnnotation,
 .annotationLayer .lineAnnotation svg line,
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -4545,20 +4545,20 @@ exports.PDFAttachmentViewer = PDFAttachm
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFDocumentProperties = void 0;
 
+var _pdfjsLib = __webpack_require__(4);
+
 var _ui_utils = __webpack_require__(2);
 
-var _pdfjsLib = __webpack_require__(4);
-
 const DEFAULT_FIELD_CONTENT = '-';
 const NON_METRIC_LOCALES = ['en-us', 'en-lr', 'my'];
 const US_PAGE_NAMES = {
   '8.5x11': 'Letter',
   '8.5x14': 'Legal'
 };
 const METRIC_PAGE_NAMES = {
   '297x420': 'A3',
@@ -4812,51 +4812,26 @@ class PDFDocumentProperties {
         unit,
         name,
         orientation
       }, '{{width}} × {{height}} {{unit}} (' + (name ? '{{name}}, ' : '') + '{{orientation}})');
     });
   }
 
   _parseDate(inputDate) {
-    if (!inputDate) {
-      return;
-    }
-
-    let dateToParse = inputDate;
-
-    if (dateToParse.substring(0, 2) === 'D:') {
-      dateToParse = dateToParse.substring(2);
-    }
-
-    let year = parseInt(dateToParse.substring(0, 4), 10);
-    let month = parseInt(dateToParse.substring(4, 6), 10) - 1;
-    let day = parseInt(dateToParse.substring(6, 8), 10);
-    let hours = parseInt(dateToParse.substring(8, 10), 10);
-    let minutes = parseInt(dateToParse.substring(10, 12), 10);
-    let seconds = parseInt(dateToParse.substring(12, 14), 10);
-    let utRel = dateToParse.substring(14, 15);
-    let offsetHours = parseInt(dateToParse.substring(15, 17), 10);
-    let offsetMinutes = parseInt(dateToParse.substring(18, 20), 10);
-
-    if (utRel === '-') {
-      hours += offsetHours;
-      minutes += offsetMinutes;
-    } else if (utRel === '+') {
-      hours -= offsetHours;
-      minutes -= offsetMinutes;
-    }
-
-    let date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
-    let dateString = date.toLocaleDateString();
-    let timeString = date.toLocaleTimeString();
-    return this.l10n.get('document_properties_date_string', {
-      date: dateString,
-      time: timeString
-    }, '{{date}}, {{time}}');
+    const dateObject = _pdfjsLib.PDFDateString.toDateObject(inputDate);
+
+    if (dateObject) {
+      const dateString = dateObject.toLocaleDateString();
+      const timeString = dateObject.toLocaleTimeString();
+      return this.l10n.get('document_properties_date_string', {
+        date: dateString,
+        time: timeString
+      }, '{{date}}, {{time}}');
+    }
   }
 
   _parseLinearization(isLinearized) {
     return this.l10n.get('document_properties_linearized_' + (isLinearized ? 'yes' : 'no'), null, isLinearized ? 'Yes' : 'No');
   }
 
 }
 
--- a/browser/extensions/pdfjs/moz.yaml
+++ b/browser/extensions/pdfjs/moz.yaml
@@ -15,15 +15,15 @@ origin:
   description: Portable Document Format (PDF) viewer that is built with HTML5
 
   # Full URL for the package's homepage/etc
   # Usually different from repository url
   url: https://github.com/mozilla/pdf.js
 
   # Human-readable identifier for this version/release
   # Generally "version NNN", "tag SSS", "bookmark SSS"
-  release: version 2.2.160
+  release: version 2.2.167
 
   # The package's license, where possible using the mnemonic from
   # https://spdx.org/licenses/
   # Multiple licenses can be specified (as a YAML list)
   # A "LICENSE" file must exist containing the full license text
   license: Apache-2.0
--- a/browser/locales/en-US/pdfviewer/viewer.properties
+++ b/browser/locales/en-US/pdfviewer/viewer.properties
@@ -221,16 +221,20 @@ page_scale_percent={{scale}}%
 
 # Loading indicator messages
 loading_error_indicator=Error
 loading_error=An error occurred while loading the PDF.
 invalid_file_error=Invalid or corrupted PDF file.
 missing_file_error=Missing PDF file.
 unexpected_response_error=Unexpected server response.
 
+# LOCALIZATION NOTE (annotation_date_string): "{{date}}" and "{{time}}" will be
+# replaced by the modification date, and time, of the annotation.
+annotation_date_string={{date}}, {{time}}
+
 # LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip.
 # "{{type}}" will be replaced with an annotation type from a list defined in
 # the PDF spec (32000-1:2008 Table 169 – Annotation types).
 # Some common types are e.g.: "Check", "Text", "Comment", "Note"
 text_annotation_type.alt=[{{type}} Annotation]
 password_label=Enter the password to open this PDF file.
 password_invalid=Invalid password. Please try again.
 password_ok=OK
--- a/dom/interfaces/base/nsIRemoteTab.idl
+++ b/dom/interfaces/base/nsIRemoteTab.idl
@@ -2,16 +2,17 @@
  * 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/. */
 
 
 #include "domstubs.idl"
 
 interface nsIPrincipal;
 webidl Element;
+webidl WindowGlobalParent;
 
 [builtinclass, scriptable, uuid(8e49f7b0-1f98-4939-bf91-e9c39cd56434)]
 interface nsIRemoteTab : nsISupports
 {
   /**
    * Manages the docshell active state of the remote browser. Setting the
    * docShell to be active will also cause it to render layers and upload
    * them to the compositor. Setting the docShell as not active will clear
@@ -64,16 +65,21 @@ interface nsIRemoteTab : nsISupports
   readonly attribute boolean hasContentOpener;
   /**
    * True if we've previously received layers for this tab when switching to
    * it.
    */
   readonly attribute boolean hasPresented;
 
   /**
+   * Gets all of the WindowGlobalParent actors for this remote tab.
+   */
+  readonly attribute Array<WindowGlobalParent> windowGlobalParents;
+
+  /**
    * Ensures that the content process which has this remote tab has all of the
    * permissions required to load a document with the given principal.
    */
   void transmitPermissionsForPrincipal(in nsIPrincipal aPrincipal);
 
   /**
    * True if any of the frames loaded in the tab have registered
    * an onbeforeunload event handler.
--- a/dom/ipc/BrowserBridgeParent.cpp
+++ b/dom/ipc/BrowserBridgeParent.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "mozilla/dom/BrowserBridgeParent.h"
+#include "mozilla/dom/BrowserParent.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentProcessManager.h"
 #include "mozilla/dom/CanonicalBrowsingContext.h"
 #include "mozilla/dom/BrowsingContextGroup.h"
 #include "mozilla/layers/InputAPZContext.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::layout;
@@ -94,16 +95,25 @@ nsresult BrowserBridgeParent::Init(const
     return NS_ERROR_FAILURE;
   }
 
   // Send the newly created layers ID back into content.
   Unused << SendSetLayersId(rf->GetLayersId());
   return NS_OK;
 }
 
+CanonicalBrowsingContext* BrowserBridgeParent::GetBrowsingContext() {
+  return mBrowserParent->GetBrowsingContext();
+}
+
+BrowserParent* BrowserBridgeParent::Manager() {
+  MOZ_ASSERT(mIPCOpen);
+  return static_cast<BrowserParent*>(PBrowserBridgeParent::Manager());
+}
+
 void BrowserBridgeParent::Destroy() {
   if (mBrowserParent) {
     mBrowserParent->Destroy();
     mBrowserParent = nullptr;
   }
 }
 
 IPCResult BrowserBridgeParent::RecvShow(const ScreenIntSize& aSize,
--- a/dom/ipc/BrowserBridgeParent.h
+++ b/dom/ipc/BrowserBridgeParent.h
@@ -3,21 +3,22 @@
 /* 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/. */
 
 #ifndef mozilla_dom_BrowserBridgeParent_h
 #define mozilla_dom_BrowserBridgeParent_h
 
 #include "mozilla/dom/PBrowserBridgeParent.h"
-#include "mozilla/dom/BrowserParent.h"
 
 namespace mozilla {
 namespace dom {
 
+class BrowserParent;
+
 /**
  * BrowserBridgeParent implements the parent actor part of the PBrowserBridge
  * protocol. See PBrowserBridge for more information.
  */
 class BrowserBridgeParent : public PBrowserBridgeParent {
  public:
   NS_INLINE_DECL_REFCOUNTING(BrowserBridgeParent);
 
@@ -25,25 +26,20 @@ class BrowserBridgeParent : public PBrow
 
   // Initialize this actor after performing startup.
   nsresult Init(const nsString& aPresentationURL, const nsString& aRemoteType,
                 CanonicalBrowsingContext* aBrowsingContext,
                 const uint32_t& aChromeFlags);
 
   BrowserParent* GetBrowserParent() { return mBrowserParent; }
 
-  CanonicalBrowsingContext* GetBrowsingContext() {
-    return mBrowserParent->GetBrowsingContext();
-  }
+  CanonicalBrowsingContext* GetBrowsingContext();
 
   // Get our manager actor.
-  BrowserParent* Manager() {
-    MOZ_ASSERT(mIPCOpen);
-    return static_cast<BrowserParent*>(PBrowserBridgeParent::Manager());
-  }
+  BrowserParent* Manager();
 
   // Tear down this BrowserBridgeParent.
   void Destroy();
 
  protected:
   friend class PBrowserBridgeParent;
 
   mozilla::ipc::IPCResult RecvShow(const ScreenIntSize& aSize,
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -535,24 +535,19 @@ void BrowserParent::SetOwnerElement(Elem
   }
 
   // Set our BrowsingContext's embedder if we're not embedded within a
   // BrowserBridgeParent.
   if (!GetBrowserBridgeParent() && mBrowsingContext) {
     mBrowsingContext->SetEmbedderElement(mFrameElement);
   }
 
-  // Ensure all BrowserParent actors within BrowserBridges are also updated.
-  const auto& browserBridges = ManagedPBrowserBridgeParent();
-  for (auto iter = browserBridges.ConstIter(); !iter.Done(); iter.Next()) {
-    BrowserBridgeParent* browserBridge =
-        static_cast<BrowserBridgeParent*>(iter.Get()->GetKey());
-
-    browserBridge->GetBrowserParent()->SetOwnerElement(aElement);
-  }
+  VisitChildren([aElement](BrowserBridgeParent* aBrowser) {
+    aBrowser->GetBrowserParent()->SetOwnerElement(aElement);
+  });
 }
 
 NS_IMETHODIMP BrowserParent::GetOwnerElement(Element** aElement) {
   *aElement = do_AddRef(GetOwnerElement()).take();
   return NS_OK;
 }
 
 void BrowserParent::CacheFrameLoader(nsFrameLoader* aFrameLoader) {
@@ -3250,16 +3245,31 @@ BrowserParent::GetHasPresented(bool* aRe
   return NS_OK;
 }
 
 void BrowserParent::NavigateByKey(bool aForward, bool aForDocumentNavigation) {
   Unused << SendNavigateByKey(aForward, aForDocumentNavigation);
 }
 
 NS_IMETHODIMP
+BrowserParent::GetWindowGlobalParents(
+    nsTArray<RefPtr<WindowGlobalParent>>& aWindowGlobalParents) {
+  VisitAll([&aWindowGlobalParents](BrowserParent* aBrowser) {
+    const auto& windowGlobalParents = aBrowser->ManagedPWindowGlobalParent();
+    for (auto iter = windowGlobalParents.ConstIter(); !iter.Done();
+         iter.Next()) {
+      WindowGlobalParent* windowGlobalParent =
+          static_cast<WindowGlobalParent*>(iter.Get()->GetKey());
+      aWindowGlobalParents.AppendElement(windowGlobalParent);
+    }
+  });
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 BrowserParent::TransmitPermissionsForPrincipal(nsIPrincipal* aPrincipal) {
   return Manager()->TransmitPermissionsForPrincipal(aPrincipal);
 }
 
 NS_IMETHODIMP
 BrowserParent::GetHasBeforeUnload(bool* aResult) {
   *aResult = mHasBeforeUnload;
   return NS_OK;
--- a/dom/ipc/BrowserParent.h
+++ b/dom/ipc/BrowserParent.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_dom_BrowserParent_h
 #define mozilla_dom_BrowserParent_h
 
 #include "js/TypeDecls.h"
 #include "LiveResizeListener.h"
 #include "mozilla/ContentCache.h"
 #include "mozilla/dom/ipc/IdType.h"
+#include "mozilla/dom/BrowserBridgeParent.h"
 #include "mozilla/dom/PBrowserParent.h"
 #include "mozilla/dom/PContent.h"
 #include "mozilla/dom/PFilePickerParent.h"
 #include "mozilla/dom/TabContext.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/gfx/CrossProcessPaint.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
@@ -67,17 +68,16 @@ class DataSourceSurface;
 
 namespace dom {
 
 class CanonicalBrowsingContext;
 class ClonedMessageData;
 class ContentParent;
 class Element;
 class DataTransfer;
-class BrowserBridgeParent;
 
 namespace ipc {
 class StructuredCloneData;
 }  // namespace ipc
 
 /**
  * BrowserParent implements the parent actor part of the PBrowser protocol. See
  * PBrowser for more information.
@@ -182,16 +182,56 @@ class BrowserParent final : public PBrow
   ShowInfo GetShowInfo();
 
   /**
    * Let managees query if Destroy() is already called so they don't send out
    * messages when the PBrowser actor is being destroyed.
    */
   bool IsDestroyed() const { return mIsDestroyed; }
 
+  /*
+   * Visit each BrowserParent in the tree formed by PBrowser and
+   * PBrowserBridge, including `this`.
+   */
+  template <typename Callback>
+  void VisitAll(Callback aCallback) {
+    aCallback(this);
+    VisitAllDescendants(aCallback);
+  }
+
+  /*
+   * Visit each BrowserParent in the tree formed by PBrowser and
+   * PBrowserBridge, excluding `this`.
+   */
+  template <typename Callback>
+  void VisitAllDescendants(Callback aCallback) {
+    const auto& browserBridges = ManagedPBrowserBridgeParent();
+    for (auto iter = browserBridges.ConstIter(); !iter.Done(); iter.Next()) {
+      BrowserBridgeParent* browserBridge =
+          static_cast<BrowserBridgeParent*>(iter.Get()->GetKey());
+      BrowserParent* browserParent = browserBridge->GetBrowserParent();
+
+      aCallback(browserParent);
+      browserParent->VisitAllDescendants(aCallback);
+    }
+  }
+
+  /*
+   * Visit each BrowserBridgeParent that is a child of this BrowserParent.
+   */
+  template <typename Callback>
+  void VisitChildren(Callback aCallback) {
+    const auto& browserBridges = ManagedPBrowserBridgeParent();
+    for (auto iter = browserBridges.ConstIter(); !iter.Done(); iter.Next()) {
+      BrowserBridgeParent* browserBridge =
+          static_cast<BrowserBridgeParent*>(iter.Get()->GetKey());
+      aCallback(browserBridge);
+    }
+  }
+
   void SetOwnerElement(Element* aElement);
 
   void SetBrowserDOMWindow(nsIBrowserDOMWindow* aBrowserDOMWindow) {
     mBrowserDOMWindow = aBrowserDOMWindow;
   }
 
   void SetHasContentOpener(bool aHasContentOpener);
 
--- a/dom/svg/SVGTests.h
+++ b/dom/svg/SVGTests.h
@@ -91,16 +91,17 @@ class SVGTests : public nsISupports {
   void GetAttrValue(uint8_t aAttrEnum, nsAttrValue& aValue) const;
 
   void MaybeInvalidate();
 
   // WebIDL
   already_AddRefed<DOMSVGStringList> RequiredFeatures();
   already_AddRefed<DOMSVGStringList> RequiredExtensions();
   already_AddRefed<DOMSVGStringList> SystemLanguage();
+
   bool HasExtension(const nsAString& aExtension) const;
 
   virtual SVGElement* AsSVGElement() = 0;
 
   const SVGElement* AsSVGElement() const {
     return const_cast<SVGTests*>(this)->AsSVGElement();
   }
 
--- a/dom/webidl/SVGTests.webidl
+++ b/dom/webidl/SVGTests.webidl
@@ -11,12 +11,10 @@
  */
 
 [NoInterfaceObject]
 interface SVGTests {
 
   readonly attribute SVGStringList requiredFeatures;
   readonly attribute SVGStringList requiredExtensions;
   readonly attribute SVGStringList systemLanguage;
-
-  boolean hasExtension(DOMString extension);
 };
 
--- a/layout/mathml/tests/test_disabled_chrome.html
+++ b/layout/mathml/tests/test_disabled_chrome.html
@@ -37,18 +37,15 @@ https://bugzilla.mozilla.org/show_bug.cg
     let loadPromise = ContentTaskUtils.waitForEvent(iframeEl, 'load', false);
     t.appendChild(iframeEl);
     await loadPromise;
 
     const contentBR = iframeEl.contentDocument.body.getBoundingClientRect();
 
     ok(chromeBR.height > contentBR.height, "Chrome content height should be bigger than content due to layout");
 
-    ok(!iframeEl.contentDocument.getElementById('svgel').hasExtension("http://www.w3.org/1998/Math/MathML"), 'SVG namespace support is disabled in content iframe');
-    ok(chromeIframeEl.contentDocument.getElementById('svgel').hasExtension("http://www.w3.org/1998/Math/MathML"), 'SVG namespace support is enabled in chrome iframe');
-
     SpecialPowers.setBoolPref("mathml.disabled", initialPrefValue);
   });
 </script>
 </pre>
 </body>
 </html>
 
--- a/layout/svg/tests/test_disabled_chrome.html
+++ b/layout/svg/tests/test_disabled_chrome.html
@@ -33,19 +33,16 @@ https://bugzilla.mozilla.org/show_bug.cg
     iframeEl.src = url;
     let loadPromise = ContentTaskUtils.waitForEvent(iframeEl, 'load', false);
     t.appendChild(iframeEl);
     await loadPromise;
 
     const contentBR = iframeEl.contentDocument.body.getBoundingClientRect();
     ok(chromeBR.height > contentBR.height, "Chrome content height should be bigger than content due to layout");
 
-    ok(!("hasExtension" in iframeEl.contentDocument.getElementById('svgel')), 'SVG is disabled so no hasExtension support is available in content iframe');
-    ok(chromeIframeEl.contentDocument.getElementById('svgel').hasExtension("http://www.w3.org/1998/Math/MathML"), 'SVG namespace support is enabled in chrome iframe');
-
     url = "http://mochi.test:8888/chrome/layout/svg/tests/svg_example_script.svg";
     const iframeElScript = document.createElement("iframe");
     let loadPromiseScript = ContentTaskUtils.waitForEvent(iframeElScript, "load", false);
     iframeElScript.src = url;
     t.appendChild(iframeElScript);
     await loadPromiseScript;
     ok(!iframeElScript.contentDocument.documentElement.style, "Content should not be styled");
 
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mathml/relations/html5-tree/required-extensions-1.html.ini
@@ -0,0 +1,4 @@
+[required-extensions-1.html]
+  [Testing foreignObject.hasExtension('http://www.w3.org/1998/Math/MathML')]
+    expected: FAIL
+
--- a/testing/web-platform/meta/svg/historical.html.ini
+++ b/testing/web-platform/meta/svg/historical.html.ini
@@ -3,17 +3,14 @@
     expected: FAIL
 
   [SVGZoomAndPan mixin interface must not be exposed]
     expected: FAIL
 
   [SVGGraphicsElement.prototype.getTransformToElement must be removed]
     expected: FAIL
 
-  [SVGGraphicsElement.prototype.hasExtension must be removed]
-    expected: FAIL
-
   [SVGGraphicsElement.prototype.requiredFeatures must be removed]
     expected: FAIL
 
   [SVGSVGElement.prototype.useCurrentView must be removed]
     expected: FAIL