Bug 1511943 - Inject WebExtension "browser" object into CloudFile provider pages; r=Fallen
authorGeoff Lankow <geoff@darktrojan.net>
Thu, 13 Dec 2018 20:08:32 +1300
changeset 33987 57e4b9bf11add713ac5e558d3c1ccc9a954b8892
parent 33986 1f0bcf57572f4f1972ec9d5fc1d661ec2ef5d13c
child 33988 995d9cb811609c8ec14086aca430c93919d62ad9
push id389
push userclokep@gmail.com
push dateMon, 18 Mar 2019 19:01:53 +0000
reviewersFallen
bugs1511943
Bug 1511943 - Inject WebExtension "browser" object into CloudFile provider pages; r=Fallen
mail/components/cloudfile/content/addAccountDialog.js
mail/components/extensions/ext-mail.json
mail/components/extensions/schemas/cloudFile.json
mail/components/preferences/preferencesTab.js
--- a/mail/components/cloudfile/content/addAccountDialog.js
+++ b/mail/components/cloudfile/content/addAccountDialog.js
@@ -4,16 +4,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/. */
 
 var kFormId = "provider-form";
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource:///modules/cloudFileAccounts.js");
+ChromeUtils.defineModuleGetter(this, "ExtensionParent", "resource://gre/modules/ExtensionParent.jsm");
 
 function createAccountObserver() {}
 
 createAccountObserver.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIRequestObserver]),
   onStartRequest(aRequest, aContext) {},
   onStopRequest(aRequest, aContext, aStatusCode) {
     if (aStatusCode == Cr.NS_OK
@@ -151,36 +152,47 @@ var addAccountDialog = {
       this._settings.style.height = this._settings.style.minHeight = "16px";
       return;
     }
     let newHeight = this._settings.contentDocument.body.offsetHeight;
     this._settings.style.height = this._settings.style.minHeight = newHeight + "px";
     window.sizeToContent();
   },
 
-  switchIframeType(type, src) {
+  /**
+   * Displays the provider's settingsURL in a browser element, using a
+   * chrome-privileged browser only if necessary.
+   */
+  setIFrameSource(src) {
+    let type = src.startsWith("chrome:") ? "chrome" : "content";
     if (type == this._settings.getAttribute("type")) {
+      this._settings.setAttribute("src", src);
       return;
     }
 
-    let frame = document.createElement("iframe");
+    let frame = document.createElement("browser");
     frame.setAttribute("class", "indent");
     frame.setAttribute("allowfullscreen", "false");
     frame.setAttribute("flex", "1");
     frame.setAttribute("type", type);
-    frame.setAttribute("src", src);
 
     // allows keeping dialog background color without hoops
     frame.setAttribute("transparent", "true");
 
     this._settings.parentNode.replaceChild(frame, this._settings);
     this._settings = frame;
 
     this._settings.addEventListener("DOMContentLoaded", this);
     this._settings.addEventListener("overflow", this);
+
+    if (src.startsWith("moz-extension:")) {
+      ExtensionParent.apiManager.emit("extension-browser-inserted", frame);
+    }
+
+    frame.setAttribute("src", src);
   },
 
   removeTitleMenuItem() {
     let menuitem = this._accountType.querySelector('menuitem[value=""]');
     if (menuitem)
       menuitem.remove();
   },
 
@@ -272,18 +284,17 @@ var addAccountDialog = {
     let provider = cloudFileAccounts.getProviderForType(providerKey);
     if (!provider)
       return;
 
     // Reset the message display
     this._messages.selectedIndex = -1;
 
     // Load up the correct XHTML page for this provider.
-    let type = provider.settingsURL.startsWith("chrome:") ? "chrome" : "content";
-    this.switchIframeType(type, provider.settingsURL);
+    this.setIFrameSource(provider.settingsURL);
   },
 
   onClickLink(e) {
     e.preventDefault();
     let href = e.target.getAttribute("href");
     gProtocolService.loadURI(Services.io.newURI(href, "UTF-8"));
   },
 
--- a/mail/components/extensions/ext-mail.json
+++ b/mail/components/extensions/ext-mail.json
@@ -14,17 +14,17 @@
     "manifest": ["browser_action"],
     "paths": [
       ["browserAction"]
     ]
   },
   "cloudFile": {
     "url": "chrome://messenger/content/parent/ext-cloudFile.js",
     "schema": "chrome://messenger/content/schemas/cloudFile.json",
-    "scopes": ["addon_parent"],
+    "scopes": ["addon_parent", "content_parent"],
     "manifest": ["cloud_file"],
     "paths": [
       ["cloudFile"]
     ]
   },
   "composeAction": {
     "url": "chrome://messenger/content/parent/ext-composeAction.js",
     "schema": "chrome://messenger/content/schemas/composeAction.json",
--- a/mail/components/extensions/schemas/cloudFile.json
+++ b/mail/components/extensions/schemas/cloudFile.json
@@ -37,16 +37,17 @@
             "optional": true
           }
         }
       }
     ]
   },
   {
     "namespace": "cloudFile",
+    "allowedContexts": ["content"],
     "events": [
       {
         "name": "onFileUpload",
         "type": "function",
         "description": "Fired when a file should be uploaded to the cloud file provider",
         "parameters": [
           {
             "name": "account",
@@ -139,20 +140,22 @@
         "id": "CloudFileAccount",
         "type": "object",
         "description": "Information about a cloud file account",
         "properties": {
           "id": {
             "type": "string"
           },
           "configured": {
-            "type": "boolean"
+            "type": "boolean",
+            "description": "If true, the account is configured and ready to use. This property is currently ignored and all accounts are assumed to be configured."
           },
           "name": {
-            "type": "string"
+            "type": "string",
+            "description": "A user-friendly name for this account."
           },
           "uploadSizeLimit": {
             "type": "integer",
             "minimum": -1,
             "optional": true,
             "description": "The maximum size in bytes for a single file to upload. Set to -1 if unlimited."
           },
           "spaceRemaining": {
@@ -197,48 +200,52 @@
         }
       }
     ],
     "functions": [
       {
         "name": "getAccount",
         "type": "function",
         "description": "Retrieve information about a single cloud file account",
+        "allowedContexts": ["content"],
         "async": true,
         "parameters": [
           {
             "name": "accountId",
             "type": "string"
           }
         ]
       },
       {
         "name": "getAllAccounts",
         "type": "function",
         "description": "Retrieve all cloud file accounts for the current add-on",
-        "parameters": [],
-        "async": true
+        "allowedContexts": ["content"],
+        "async": true,
+        "parameters": []
       },
       {
         "name": "updateAccount",
         "type": "function",
         "description": "Update a cloud file account",
+        "allowedContexts": ["content"],
+        "async": true,
         "parameters": [
           {
             "name": "accountId",
             "type": "string"
           },
           {
             "name": "updateProperties",
             "type": "object",
             "properties": {
               "configured": {
                 "type": "boolean",
                 "optional": true,
-                "description": "If true, the account is configured and ready to use."
+                "description": "If true, the account is configured and ready to use. This property is currently ignored and all accounts are assumed to be configured."
               },
               "uploadSizeLimit": {
                 "type": "integer",
                 "minimum": -1,
                 "optional": true,
                 "description": "The maximum size in bytes for a single file to upload. Set to -1 if unlimited."
               },
               "spaceRemaining": {
@@ -260,14 +267,13 @@
               },
               "settingsUrl": {
                 "type": "string",
                 "format": "relativeUrl",
                 "optional": true
               }
             }
           }
-        ],
-        "async": true
+        ]
       }
     ]
   }
 ]
--- a/mail/components/preferences/preferencesTab.js
+++ b/mail/components/preferences/preferencesTab.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // mail/base/content/specialTabs.js
 /* globals contentTabBaseType, DOMLinkHandler */
 
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 ChromeUtils.import("resource:///modules/errUtils.js");
+ChromeUtils.defineModuleGetter(this, "ExtensionParent", "resource://gre/modules/ExtensionParent.jsm");
 
 var gPrefTab = null;
 
 /**
  * A tab to show Preferences.
  */
 var preferencesTabType = {
   __proto__: contentTabBaseType,
@@ -108,16 +109,17 @@ var preferencesTabType = {
 
     // Initialize our unit testing variables.
     aTab.pageLoading = true;
     aTab.pageLoaded = false;
 
     // Now start loading the content.
     aTab.title = this.loadingTabString;
 
+    ExtensionParent.apiManager.emit("extension-browser-inserted", aTab.browser);
     let params = {
       triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
       postData: aArgs.postData || null,
     };
     aTab.browser.loadURI(aArgs.contentPage, params);
 
     gPrefTab = aTab;
     this.lastBrowserId++;