Bug 1338195 - Define a `frame-script` environment for eslint and use it to clear no-undef issues for known frame script globals. r?Mossop draft
authorMark Banner <standard8@mozilla.com>
Tue, 07 Feb 2017 10:52:06 +0000
changeset 485178 a10875ac77b0112059fa9bc2c8e74c4276c3889d
parent 485098 a9ec72f82299250e6023988e238931bbca0ef7fa
child 545955 33ecc93de2d881e999a3f4813e894448ec084b41
push id45666
push userbmo:standard8@mozilla.com
push dateThu, 16 Feb 2017 09:07:34 +0000
reviewersMossop
bugs1338195
milestone54.0a1
Bug 1338195 - Define a `frame-script` environment for eslint and use it to clear no-undef issues for known frame script globals. r?Mossop MozReview-Commit-ID: Fcin4InbLK2
browser/base/content/aboutTabCrashed.js
browser/base/content/content.js
browser/base/content/social-content.js
browser/base/content/tab-content.js
browser/base/content/test/general/aboutHome_content_script.js
browser/base/content/test/general/browser_accesskeys.js
browser/base/content/test/general/browser_backButtonFitts.js
browser/base/content/test/general/browser_documentnavigation.js
browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
browser/base/content/test/general/browser_e10s_switchbrowser.js
browser/base/content/test/general/browser_offlineQuotaNotification.js
browser/base/content/test/general/browser_restore_isAppTab.js
browser/base/content/test/general/browser_tab_dragdrop.js
browser/base/content/test/general/browser_tabfocus.js
browser/base/content/test/general/browser_windowactivation.js
browser/base/content/test/general/contentSearchUI.js
browser/base/content/test/general/content_aboutAccounts.js
browser/base/content/test/general/head.js
browser/base/content/test/newtab/browser_newtab_bug734043.js
browser/base/content/test/newtab/browser_newtab_bug991111.js
browser/base/content/test/newtab/browser_newtab_bug998387.js
browser/base/content/test/newtab/browser_newtab_search.js
browser/base/content/test/newtab/content-reflows.js
browser/base/content/test/social/browser_share.js
browser/base/content/test/social/social_crash_content_helper.js
browser/base/content/test/urlbar/head.js
browser/base/content/test/urlbar/urlbarAddonIframeContentScript.js
browser/base/content/test/webrtc/get_user_media_content_script.js
browser/components/safebrowsing/content/test/browser_bug400731.js
browser/components/uitour/content-UITour.js
toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js
toolkit/components/addoncompat/tests/addon/bootstrap.js
toolkit/components/addoncompat/tests/compat-addon/bootstrap.js
toolkit/components/alerts/test/test_alerts_noobserve.html
toolkit/components/alerts/test/test_alerts_requireinteraction.html
toolkit/components/alerts/test/test_multiple_alerts.html
toolkit/components/alerts/test/test_principal.html
toolkit/components/formautofill/test/chrome/loader_parent.js
toolkit/components/gfx/content/gfxFrameScript.js
toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/content/framescript.js
toolkit/components/perfmonitoring/tests/browser/browser_compartments.js
toolkit/components/perfmonitoring/tests/browser/head.js
toolkit/components/prompts/test/chromeScript.js
toolkit/components/satchel/formSubmitListener.js
toolkit/components/satchel/test/parent_utils.js
toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
toolkit/components/thumbnails/test/thumbnails_crash_content_helper.js
toolkit/components/viewsource/content/viewSource-content.js
toolkit/content/browser-child.js
toolkit/content/browser-content.js
toolkit/content/plugins.html
toolkit/content/tests/mochitest/test_autocomplete_change_after_focus.html
tools/lint/docs/linters/eslint-plugin-mozilla.rst
tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
tools/lint/eslint/eslint-plugin-mozilla/lib/index.js
tools/lint/eslint/eslint-plugin-mozilla/package.json
--- a/browser/base/content/aboutTabCrashed.js
+++ b/browser/base/content/aboutTabCrashed.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+
 var AboutTabCrashed = {
   /**
    * This can be set to true once this page receives a message from the
    * parent saying whether or not a crash report is available.
    */
   hasReport: false,
 
   /**
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -1,16 +1,18 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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/. */
 
 /* This content script should work in any browser or iframe and should not
  * depend on the frame being contained in tabbrowser. */
 
+/* eslint-env mozilla/frame-script */
+
 var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource:///modules/ContentWebRTC.jsm");
 Cu.import("resource:///modules/ContentObservers.jsm");
 Cu.import("resource://gre/modules/InlineSpellChecker.jsm");
 Cu.import("resource://gre/modules/InlineSpellCheckerContent.jsm");
--- a/browser/base/content/social-content.js
+++ b/browser/base/content/social-content.js
@@ -1,15 +1,17 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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/. */
 
 /* This content script is intended for use by iframes in the share panel. */
 
+/* eslint-env mozilla/frame-script */
+
 var {interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 // social frames are always treated as app tabs
 docShell.isAppTab = true;
 
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -1,15 +1,17 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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/. */
 
 /* This content script contains code that requires a tab browser. */
 
+/* eslint-env mozilla/frame-script */
+
 var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/ExtensionContent.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils",
   "resource:///modules/E10SUtils.jsm");
--- a/browser/base/content/test/general/aboutHome_content_script.js
+++ b/browser/base/content/test/general/aboutHome_content_script.js
@@ -1,6 +1,8 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 addMessageListener("AboutHome:SearchTriggered", function(msg) {
   sendAsyncMessage("AboutHomeTest:CheckRecordedSearch", msg.data);
 });
--- a/browser/base/content/test/general/browser_accesskeys.js
+++ b/browser/base/content/test/general/browser_accesskeys.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 add_task(function *() {
   yield pushPrefs(["ui.key.contentAccess", 5], ["ui.key.chromeAccess", 5]);
 
   const gPageURL1 = "data:text/html,<body><p>" +
                     "<button id='button' accesskey='y'>Button</button>" +
                     "<input id='checkbox' type='checkbox' accesskey='z'>Checkbox" +
                     "</p></body>";
   let tab1 = yield BrowserTestUtils.openNewForegroundTab(gBrowser, gPageURL1);
--- a/browser/base/content/test/general/browser_backButtonFitts.js
+++ b/browser/base/content/test/general/browser_backButtonFitts.js
@@ -1,12 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+/* eslint-env mozilla/frame-script */
+
 add_task(function* () {
   let firstLocation = "http://example.org/browser/browser/base/content/test/general/dummy_page.html";
   yield BrowserTestUtils.openNewForegroundTab(gBrowser, firstLocation);
 
   yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
     // Push the state before maximizing the window and clicking below.
     content.history.pushState("page2", "page2", "page2");
 
--- a/browser/base/content/test/general/browser_documentnavigation.js
+++ b/browser/base/content/test/general/browser_documentnavigation.js
@@ -1,14 +1,16 @@
 /*
  * This test checks that focus is adjusted properly in a browser when pressing F6 and Shift+F6.
  * There are additional tests in dom/tests/mochitest/chrome/test_focus_docnav.xul which test
  * non-browser cases.
  */
 
+/* eslint-env mozilla/frame-script */
+
 var testPage1 = "data:text/html,<html id='html1'><body id='body1'><button id='button1'>Tab 1</button></body></html>";
 var testPage2 = "data:text/html,<html id='html2'><body id='body2'><button id='button2'>Tab 2</button></body></html>";
 var testPage3 = "data:text/html,<html id='html3'><body id='body3' contenteditable='true'><button id='button3'>Tab 3</button></body></html>";
 
 var fm = Services.focus;
 
 function* expectFocusOnF6(backward, expectedDocument, expectedElement, onContent, desc) {
   let focusChangedInChildResolver = null;
--- a/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
+++ b/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 "use strict";
 
 var gMessageManager;
 
 function frameScript() {
   addMessageListener("Test:RequestFullscreen", () => {
     content.document.body.requestFullscreen();
   });
--- a/browser/base/content/test/general/browser_e10s_switchbrowser.js
+++ b/browser/base/content/test/general/browser_e10s_switchbrowser.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 requestLongerTimeout(2);
 
 const DUMMY_PATH = "browser/browser/base/content/test/general/dummy_page.html";
 
 const gExpectedHistory = {
   index: -1,
   entries: []
 };
--- a/browser/base/content/test/general/browser_offlineQuotaNotification.js
+++ b/browser/base/content/test/general/browser_offlineQuotaNotification.js
@@ -1,13 +1,15 @@
 /**
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+/* eslint-env mozilla/frame-script */
+
 // Test offline quota warnings - must be run as a mochitest-browser test or
 // else the test runner gets in the way of notifications due to bug 857897.
 
 const URL = "http://mochi.test:8888/browser/browser/base/content/test/general/offlineQuotaNotification.html";
 
 registerCleanupFunction(function() {
   // Clean up after ourself
   let uri = Services.io.newURI(URL);
--- a/browser/base/content/test/general/browser_restore_isAppTab.js
+++ b/browser/base/content/test/general/browser_restore_isAppTab.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 const {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
 
 const DUMMY = "http://example.com/browser/browser/base/content/test/general/dummy_page.html";
 
 function getMinidumpDirectory() {
   let dir = Services.dirsvc.get("ProfD", Ci.nsIFile);
   dir.append("minidumps");
   return dir;
--- a/browser/base/content/test/general/browser_tab_dragdrop.js
+++ b/browser/base/content/test/general/browser_tab_dragdrop.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 function swapTabsAndCloseOther(a, b) {
   gBrowser.swapBrowsersAndCloseOther(gBrowser.tabs[b], gBrowser.tabs[a]);
 }
 
 var getClicks = function(tab) {
   return ContentTask.spawn(tab.linkedBrowser, {}, function() {
     return content.wrappedJSObject.clicks;
   });
--- a/browser/base/content/test/general/browser_tabfocus.js
+++ b/browser/base/content/test/general/browser_tabfocus.js
@@ -1,12 +1,14 @@
 /*
  * This test checks that focus is adjusted properly when switching tabs.
  */
 
+/* eslint-env mozilla/frame-script */
+
 var testPage1 = "<html id='html1'><body id='body1'><button id='button1'>Tab 1</button></body></html>";
 var testPage2 = "<html id='html2'><body id='body2'><button id='button2'>Tab 2</button></body></html>";
 var testPage3 = "<html id='html3'><body id='body3'><button id='button3'>Tab 3</button></body></html>";
 
 const fm = Services.focus;
 
 function EventStore() {
   this["main-window"] = [];
--- a/browser/base/content/test/general/browser_windowactivation.js
+++ b/browser/base/content/test/general/browser_windowactivation.js
@@ -1,12 +1,14 @@
 /*
  * This test checks that window activation state is set properly with multiple tabs.
  */
 
+/* eslint-env mozilla/frame-script */
+
 var testPage = "data:text/html,<body><style>:-moz-window-inactive { background-color: red; }</style><div id='area'></div></body>";
 
 var colorChangeNotifications = 0;
 var otherWindow;
 
 var browser1, browser2;
 
 function test() {
--- a/browser/base/content/test/general/contentSearchUI.js
+++ b/browser/base/content/test/general/contentSearchUI.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 "use strict";
 
 (function() {
 
 const TEST_MSG = "ContentSearchUIControllerTest";
 const ENGINE_NAME = "browser_searchSuggestionEngine searchSuggestionEngine.xml";
 var gController;
 
--- a/browser/base/content/test/general/content_aboutAccounts.js
+++ b/browser/base/content/test/general/content_aboutAccounts.js
@@ -1,15 +1,17 @@
 /* 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/. */
 
 // This file is loaded as a "content script" for browser_aboutAccounts tests
 "use strict";
 
+/* eslint-env mozilla/frame-script */
+
 var {interfaces: Ci, utils: Cu} = Components;
 
 addEventListener("load", function load(event) {
   if (event.target != content.document) {
     return;
   }
 //  content.document.removeEventListener("load", load, true);
   sendAsyncMessage("test:document:load");
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
   "resource://gre/modules/Promise.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
   "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
   "resource://gre/modules/PlacesUtils.jsm");
--- a/browser/base/content/test/newtab/browser_newtab_bug734043.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug734043.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 add_task(function* () {
   yield setLinks("0,1,2,3,4,5,6,7,8");
   setPinnedLinks("");
 
   yield* addNewTabPageTab();
   yield* checkGrid("0,1,2,3,4,5,6,7,8");
 
   yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
--- a/browser/base/content/test/newtab/browser_newtab_bug991111.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug991111.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 add_task(function* () {
   // set max rows to 1, to avoid scroll events by clicking middle button
   yield pushPrefs(["browser.newtabpage.rows", 1]);
   yield setLinks("-1");
   yield* addNewTabPageTab();
   // we need a second newtab to honor max rows
   yield* addNewTabPageTab();
 
--- a/browser/base/content/test/newtab/browser_newtab_bug998387.js
+++ b/browser/base/content/test/newtab/browser_newtab_bug998387.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 add_task(function* () {
   // set max rows to 1, to avoid scroll events by clicking middle button
   yield pushPrefs(["browser.newtabpage.rows", 1]);
   yield setLinks("0");
   yield* addNewTabPageTab();
   // we need a second newtab to honor max rows
   yield* addNewTabPageTab();
 
--- a/browser/base/content/test/newtab/browser_newtab_search.js
+++ b/browser/base/content/test/newtab/browser_newtab_search.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 // See browser/components/search/test/browser_*_behavior.js for tests of actual
 // searches.
 
 Cu.import("resource://gre/modules/Task.jsm");
 
 const ENGINE_NO_LOGO = {
   name: "searchEngineNoLogo.xml",
   numLogos: 0,
--- a/browser/base/content/test/newtab/content-reflows.js
+++ b/browser/base/content/test/newtab/content-reflows.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+
 (function() {
   "use strict";
 
   const Ci = Components.interfaces;
 
   docShell.addWeakReflowObserver({
     reflow() {
       // Gather information about the current code path.
--- a/browser/base/content/test/social/browser_share.js
+++ b/browser/base/content/test/social/browser_share.js
@@ -1,8 +1,9 @@
+/* eslint-env mozilla/frame-script */
 
 var SocialService = Cu.import("resource:///modules/SocialService.jsm", {}).SocialService;
 
 var baseURL = "https://example.com/browser/browser/base/content/test/social/";
 
 var manifest = { // normal provider
   name: "provider 1",
   origin: "https://example.com",
--- a/browser/base/content/test/social/social_crash_content_helper.js
+++ b/browser/base/content/test/social/social_crash_content_helper.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 var Cu = Components.utils;
 
 // Ideally we would use CrashTestUtils.jsm, but that's only available for
 // xpcshell tests - so we just copy a ctypes crasher from it.
 Cu.import("resource://gre/modules/ctypes.jsm");
 var crash = function() { // this will crash when called.
   let zero = new ctypes.intptr_t(8);
   let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
--- a/browser/base/content/test/urlbar/head.js
+++ b/browser/base/content/test/urlbar/head.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
   "resource://gre/modules/Promise.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task",
   "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
   "resource://gre/modules/PlacesUtils.jsm");
@@ -196,9 +198,8 @@ function promiseNewSearchEngine(basename
       },
       onError(errCode) {
         Assert.ok(false, "addEngine failed with error code " + errCode);
         reject();
       },
     });
   });
 }
-
--- a/browser/base/content/test/urlbar/urlbarAddonIframeContentScript.js
+++ b/browser/base/content/test/urlbar/urlbarAddonIframeContentScript.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 // Forward messages from the test to the iframe as events.
 addMessageListener("TestMessage", msg => {
   content.dispatchEvent(new content.CustomEvent("TestEvent", {
     detail: Components.utils.cloneInto(msg.data, content),
   }));
 });
 
 // Forward events from the iframe to the test as messages.
--- a/browser/base/content/test/webrtc/get_user_media_content_script.js
+++ b/browser/base/content/test/webrtc/get_user_media_content_script.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService",
                                    "@mozilla.org/mediaManagerService;1",
                                    "nsIMediaManagerService");
 
 const kObservedTopics = [
   "getUserMedia:response:allow",
   "getUserMedia:revoke",
--- a/browser/components/safebrowsing/content/test/browser_bug400731.js
+++ b/browser/components/safebrowsing/content/test/browser_bug400731.js
@@ -1,10 +1,12 @@
 /* Check presence of the "Ignore this warning" button */
 
+/* eslint-env mozilla/frame-script */
+
 function onDOMContentLoaded(callback) {
   function complete({ data }) {
     mm.removeMessageListener("Test:DOMContentLoaded", complete);
     callback(data);
   }
 
   let mm = gBrowser.selectedBrowser.messageManager;
   mm.addMessageListener("Test:DOMContentLoaded", complete);
--- a/browser/components/uitour/content-UITour.js
+++ b/browser/components/uitour/content-UITour.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+
 var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 const PREF_TEST_WHITELIST = "browser.uitour.testingOrigins";
 const UITOUR_PERMISSION   = "uitour";
 
 var UITourListener = {
   handleEvent(event) {
     if (!Services.prefs.getBoolPref("browser.uitour.enabled")) {
--- a/toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js
+++ b/toolkit/components/aboutperformance/tests/browser/browser_aboutperformance.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 "use strict";
 
 Cu.import("resource://testing-common/ContentTask.jsm", this);
 
 const URL = "http://example.com/browser/toolkit/components/aboutperformance/tests/browser/browser_compartments.html?test=" + Math.random();
 
 // This function is injected as source as a frameScript
 function frameScript() {
--- a/toolkit/components/addoncompat/tests/addon/bootstrap.js
+++ b/toolkit/components/addoncompat/tests/addon/bootstrap.js
@@ -1,8 +1,11 @@
+// This file also defines a frame script.
+/* eslint-env mozilla/frame-script */
+
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/BrowserUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -622,9 +625,8 @@ function shutdown(aData, aReason) {
   });
 }
 
 function install(aData, aReason) {
 }
 
 function uninstall(aData, aReason) {
 }
-
--- a/toolkit/components/addoncompat/tests/compat-addon/bootstrap.js
+++ b/toolkit/components/addoncompat/tests/compat-addon/bootstrap.js
@@ -1,8 +1,11 @@
+// This file defines a frame script.
+/* eslint-env mozilla/frame-script */
+
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/BrowserUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
@@ -83,9 +86,8 @@ function shutdown(aData, aReason) {
   });
 }
 
 function install(aData, aReason) {
 }
 
 function uninstall(aData, aReason) {
 }
-
--- a/toolkit/components/alerts/test/test_alerts_noobserve.html
+++ b/toolkit/components/alerts/test/test_alerts_noobserve.html
@@ -1,28 +1,29 @@
 <!DOCTYPE HTML>
 <!-- Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/ -->
 <html>
 <head>
   <title>Test for Alerts Service</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 
 <body>
 <p id="display"></p>
 
 <br>Alerts service, without observer "asynchronous" case.
 <br>
 <br>A notification should soon appear somewhere.
 <br>If there has been no crash when the notification (later) disappears, assume all is good.
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
+/* eslint-env mozilla/frame-script */
 
 const Cc = SpecialPowers.Cc;
 const Ci = SpecialPowers.Ci;
 
 const chromeScript = SpecialPowers.loadChromeScript(_ => {
   const { utils: Cu } = Components;
 
   Cu.import("resource://gre/modules/Services.jsm");
--- a/toolkit/components/alerts/test/test_alerts_requireinteraction.html
+++ b/toolkit/components/alerts/test/test_alerts_requireinteraction.html
@@ -4,16 +4,17 @@
   <title>Test for alerts with requireInteraction</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
+/* eslint-env mozilla/frame-script */
 
 const Cc = SpecialPowers.Cc;
 const Ci = SpecialPowers.Ci;
 
 const chromeScript = SpecialPowers.loadChromeScript(_ => {
   const { utils: Cu } = Components;
 
   Cu.import("resource://gre/modules/Services.jsm");
--- a/toolkit/components/alerts/test/test_multiple_alerts.html
+++ b/toolkit/components/alerts/test/test_multiple_alerts.html
@@ -1,19 +1,20 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <title>Test for multiple alerts</title>
-  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
+/* eslint-env mozilla/frame-script */
 
 const Cc = SpecialPowers.Cc;
 const Ci = SpecialPowers.Ci;
 
 const chromeScript = SpecialPowers.loadChromeScript(_ => {
   Components.utils.import("resource://gre/modules/Services.jsm");
   Components.utils.import("resource://gre/modules/Timer.jsm");
 
--- a/toolkit/components/alerts/test/test_principal.html
+++ b/toolkit/components/alerts/test/test_principal.html
@@ -7,16 +7,17 @@
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 
 <body>
 <p id="display"></p>
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
+/* eslint-env mozilla/frame-script */
 
 const Cc = SpecialPowers.Cc;
 const Ci = SpecialPowers.Ci;
 const Services = SpecialPowers.Services;
 
 const notifier = Cc["@mozilla.org/alerts-service;1"]
                    .getService(Ci.nsIAlertsService);
 
--- a/toolkit/components/formautofill/test/chrome/loader_parent.js
+++ b/toolkit/components/formautofill/test/chrome/loader_parent.js
@@ -1,11 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+// assert is available to chrome scripts loaded via SpecialPowers.loadChromeScript.
+/* global assert */
+
 /*
  * Infrastructure for the mochitest-chrome tests located in this folder, always
  * executed in the parent process.
  *
  * See "loader_common.js" in the parent folder for a general overview.
  *
  * Unless you are adding new features to the framework, you shouldn't have to
  * modify this file.  Use "head_common.js" or "head.js" for shared code.
--- a/toolkit/components/gfx/content/gfxFrameScript.js
+++ b/toolkit/components/gfx/content/gfxFrameScript.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 const gfxFrameScript = {
   domUtils: null,
 
   init() {
     let webNav = docShell.QueryInterface(Ci.nsIWebNavigation);
     let webProgress =  docShell.QueryInterface(Ci.nsIInterfaceRequestor)
--- a/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/content/framescript.js
+++ b/toolkit/components/perfmonitoring/tests/browser/browser_Addons_sample/content/framescript.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+
 "use strict";
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 function burnCPOW(msg) {
   dump(`Addon: content burnCPU start ${Math.sin(Math.random())}\n`);
   let start = content.performance.now();
   let ignored = [];
--- a/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js
+++ b/toolkit/components/perfmonitoring/tests/browser/browser_compartments.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 "use strict";
 
 /**
  * Test that we see jank that takes place in a webpage,
  * and that jank from several iframes are actually charged
  * to the top window.
  */
 Cu.import("resource://gre/modules/PerformanceStats.jsm", this);
--- a/toolkit/components/perfmonitoring/tests/browser/head.js
+++ b/toolkit/components/perfmonitoring/tests/browser/head.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 var { utils: Cu, interfaces: Ci, classes: Cc } = Components;
 
 Cu.import("resource://gre/modules/Promise.jsm", this);
 Cu.import("resource://gre/modules/AddonManager.jsm", this);
 Cu.import("resource://gre/modules/AddonWatcher.jsm", this);
 Cu.import("resource://gre/modules/PerformanceWatcher.jsm", this);
 Cu.import("resource://gre/modules/Services.jsm", this);
 Cu.import("resource://testing-common/ContentTaskUtils.jsm", this);
--- a/toolkit/components/prompts/test/chromeScript.js
+++ b/toolkit/components/prompts/test/chromeScript.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/Timer.jsm");
 
 // Define these to make EventUtils happy.
 let window = this;
 let parent = {};
 
--- a/toolkit/components/satchel/formSubmitListener.js
+++ b/toolkit/components/satchel/formSubmitListener.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+
 (function() {
 
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
--- a/toolkit/components/satchel/test/parent_utils.js
+++ b/toolkit/components/satchel/test/parent_utils.js
@@ -1,8 +1,10 @@
+/* eslint-env mozilla/frame-script */
+
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.import("resource://gre/modules/FormHistory.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://testing-common/ContentTaskUtils.jsm");
 
 var gAutocompletePopup = Services.ww.activeWindow.
                                    document.
--- a/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
+++ b/toolkit/components/thumbnails/content/backgroundPageThumbsContent.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+
 var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 Cu.importGlobalProperties(["Blob", "FileReader"]);
 
 Cu.import("resource://gre/modules/PageThumbUtils.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
--- a/toolkit/components/thumbnails/test/thumbnails_crash_content_helper.js
+++ b/toolkit/components/thumbnails/test/thumbnails_crash_content_helper.js
@@ -1,11 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */
 
+/* eslint-env mozilla/frame-script */
+
 var Cu = Components.utils;
 
 // Ideally we would use CrashTestUtils.jsm, but that's only available for
 // xpcshell tests - so we just copy a ctypes crasher from it.
 Cu.import("resource://gre/modules/ctypes.jsm");
 var crash = function() { // this will crash when called.
   let zero = new ctypes.intptr_t(8);
   let badptr = ctypes.cast(zero, ctypes.PointerType(ctypes.int32_t));
--- a/toolkit/components/viewsource/content/viewSource-content.js
+++ b/toolkit/components/viewsource/content/viewSource-content.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+
 var { utils: Cu, interfaces: Ci, classes: Cc } = Components;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
   "resource://gre/modules/BrowserUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
--- a/toolkit/content/browser-child.js
+++ b/toolkit/content/browser-child.js
@@ -1,12 +1,14 @@
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 
 Cu.import("resource://gre/modules/AppConstants.jsm");
 Cu.import("resource://gre/modules/BrowserUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
--- a/toolkit/content/browser-content.js
+++ b/toolkit/content/browser-content.js
@@ -1,13 +1,15 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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/. */
 
+/* eslint-env mozilla/frame-script */
+
 var Cc = Components.classes;
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cr = Components.results;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
@@ -1855,9 +1857,8 @@ addEventListener("mozshowdropdown", even
 addEventListener("mozshowdropdown-sourcetouch", event => {
   if (!event.isTrusted)
     return;
 
   if (!SelectContentHelper.open) {
     new SelectContentHelper(event.target, {isOpenedViaTouch: true}, this);
   }
 });
-
--- a/toolkit/content/plugins.html
+++ b/toolkit/content/plugins.html
@@ -18,16 +18,18 @@
   document.writeln("<title>" + pluginsbundle.GetStringFromName("title_label") + "<\/title>");
 </script>
 <link rel="stylesheet" type="text/css" href="chrome://global/content/plugins.css">
 <link rel="stylesheet" type="text/css" href="chrome://global/skin/plugins.css">
 </head>
 <body>
 <div id="outside">
 <script type="application/javascript">
+  /* eslint-env mozilla/frame-script */
+
   "use strict";
 
   function setDirection() {
     var frame = document.getElementById("directionDetector");
     var direction = frame.contentDocument
                          .defaultView
                          .window
                          .getComputedStyle(frame.contentDocument.getElementById("target"))
--- a/toolkit/content/tests/mochitest/test_autocomplete_change_after_focus.html
+++ b/toolkit/content/tests/mochitest/test_autocomplete_change_after_focus.html
@@ -6,16 +6,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 <head>
   <meta charset="utf-8">
   <title>Test for Bug 998893 - Ensure that input.value changes affect autocomplete</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
   <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="text/javascript">
+  /* eslint-env mozilla/frame-script */
+
   /** Test for Bug 998893 **/
   add_task(function* waitForFocus() {
     yield new Promise(resolve => SimpleTest.waitForFocus(resolve));
   });
 
   add_task(function* setup() {
     yield new Promise(resolve => {
       let chromeScript = SpecialPowers.loadChromeScript(function() {
--- a/tools/lint/docs/linters/eslint-plugin-mozilla.rst
+++ b/tools/lint/docs/linters/eslint-plugin-mozilla.rst
@@ -1,21 +1,34 @@
 =====================
 Mozilla ESLint Plugin
 =====================
 
 Environments
 ============
 
+These environments are available by specifying a comment at the top of the file,
+e.g.
+
+   /* eslint-env mozilla/chrome-worker */
+
+There are also built-in ESLint environments available as well:
+http://eslint.org/docs/user-guide/configuring#specifying-environments
+
 chrome-worker
 -------------
 
 Defines the environment for chrome workers. This differs from normal workers by
 the fact that `ctypes` can be accessed as well.
 
+frame-script
+------------
+
+Defines the environment for frame scripts.
+
 Rules
 =====
 
 avoid-removeChild
 -----------------
 
 Rejects using element.parentNode.removeChild(element) when element.remove()
 can be used instead.
new file mode 100644
--- /dev/null
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/environments/frame-script.js
@@ -0,0 +1,27 @@
+/**
+ * @fileoverview Defines the environment for frame scripts.
+ *
+ * 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 strict";
+
+module.exports = {
+  globals: {
+    addMessageListener: false,
+    addWeakMessageListener: false,
+    atob: false,
+    btoa: false,
+    content: false,
+    docShell: false,
+    privateNoteIntentionalCrash: false,
+    processMessageManager: false,
+    removeMessageListener: false,
+    removeWeakMessageListener: false,
+    sendAsyncMessage: false,
+    sendSyncMessage: false,
+    sendRpcMessage: false
+  }
+};
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/index.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/index.js
@@ -10,16 +10,17 @@
 
 //------------------------------------------------------------------------------
 // Plugin Definition
 //------------------------------------------------------------------------------
 
 module.exports = {
   environments: {
     "chrome-worker": require("../lib/environments/chrome-worker.js"),
+    "frame-script": require("../lib/environments/frame-script.js"),
   },
   processors: {
     ".xml": require("../lib/processors/xbl-bindings"),
     ".js": require("../lib/processors/self-hosted"),
   },
   rules: {
     "avoid-removeChild": require("../lib/rules/avoid-removeChild"),
     "balanced-listeners": require("../lib/rules/balanced-listeners"),
--- a/tools/lint/eslint/eslint-plugin-mozilla/package.json
+++ b/tools/lint/eslint/eslint-plugin-mozilla/package.json
@@ -1,11 +1,11 @@
 {
   "name": "eslint-plugin-mozilla",
-  "version": "0.2.21",
+  "version": "0.2.22",
   "description": "A collection of rules that help enforce JavaScript coding standard in the Mozilla project.",
   "keywords": [
     "eslint",
     "eslintplugin",
     "eslint-plugin",
     "mozilla",
     "firefox"
   ],