0

The Mozilla documentation is silent on this issue. Is there anyone in the know that can answer and explain why or why not? If not, I'd like to know the policy reasons and architectural decisions why not.

Edit: This question is limited to extensions that cannot use the Add-on SDK and instead use the traditional overlay pattern.

AlJo
  • 161
  • 1
  • 13
  • Have you tried? What happened? – John Dvorak Mar 25 '16 at 15:22
  • @JanDvorak Yes, jQuery doesn't seem to be supported directly but there may be some workarounds, but that troubles me since I don't know the intentions of the designers and whether a hack to make it work would break in the future. Not enough room to get into details here for now. – AlJo Mar 26 '16 at 00:47
  • You can inject it into any page that loads in Firefox. You can create your own html page and use it there. Mozilla docs don't mention it because it is an unrelated thing. All the docs are about the javascript used to control Firefox itself. jQuery is meant for cross browser scripting (and ease) for the web pages, not for the Firefox scope. – Noitidart Mar 28 '16 at 06:53
  • @Noitidart and the8472 jQuery is more than just a cross-browser API! It's tremendously convenient! Ever hear of "code reuse"??? Again, the Chrome browser supports 3rd party scripts in their content scripts out-of-the-box. Why do I have to explain the obvious? – AlJo Mar 30 '16 at 18:22
  • AlJo, @the8472 and I have stated the scope is different. Firefox also has "out of the box content scripts" and you can freely user jQuery there. Google Chrome does not allow customization of the browser, Firefox does, and in this scope jQuery not only is useless, but it cannot be used. Because it is a different kind of DOM. Again though, you are free to use jQuery or whatever else in your content scripts. The docs you read are regarding Firefox internals, not the internals of a content script. – Noitidart Mar 31 '16 at 00:01
  • AlJo, for intenrals of content script read here - https://developer.mozilla.org/en-US/Add-ons/SDK/Guides/Content_Scripts#Accessing_the_DOM - I use jQuery as well, i pass to the `contentScripts` attribute my path to my jquery lib file. – Noitidart Mar 31 '16 at 00:01
  • @Noitidart For reasons that I cannot recall off the top of my head, I have to use the overlay method for my extension, instead of using the add-on SDK. I will update the question. But, there should be a clear **documented** way for achieving the same thing from a frame script, imo. – AlJo Mar 31 '16 at 16:26
  • AlJo, as mentioned, you can of course include jQuery in framescript or overlay. But as mentioned the DOM in that scope is not the DOM jQuery is expected. So you will likely have errors. Give it a shot. You will also pollute the whole global scope with jQuery, unless there is a way to put it into a specific scope. jQuery animation and many of its features will be useless in that scope. Go ahead and give it a shot. In the overlay just create a script tag with jQuery. As evidence by our many comments, no matter what we say it won't convince you till you actually try it out. – Noitidart Mar 31 '16 at 23:29
  • With an overlay addon, if you are creating an `about:` page or something that that is just a webpage and that DOM is the DOM jQuery is expecting. The MDN docs you read (mentioned in OP) are of the browser DOM not the content DOM. So if you are making a html `about:` page feel free to drop in jQuery with 0 issues. With overlay you can also inject jQuery into webpages with `evalInSandbox` - https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.Sandbox#Executing_in_current_tab_scope – Noitidart Mar 31 '16 at 23:32
  • 2
    I do strongly recommend you avoid overlay. They are being deprecated. Go for classic bootstrap (2011 method) or even better use Addon SDK JPM which will for sure be supported in future https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29 – Noitidart Mar 31 '16 at 23:33
  • @Noitidart I thought I made it clear, but I'm not looking for a hack; i.e., I don't want to "pollute the whole global scope". If it cannot be done **safely**, then the answer to this question should be a simple "no". But, thanks for the links; I'll check them out. – AlJo Apr 10 '16 at 00:29
  • @AlJo you are still not understanding. If you did import it into the "chrome" scope (which is the browser xul and stuff) it would be pointless. jQuery will not work, the DOM in that scope is not what jQuery expects and it will fail. So if you ever do "pollute the whole global scope" the use of jQuery is futile. It's ok I know this "scope" of multiple DOMs is confusing, it took me awhile to get it when I first started. – Noitidart Apr 10 '16 at 04:18
  • @Noitidart Yessss, I know! I'm not asking how to make it work! I believe you! – AlJo Apr 10 '16 at 22:13
  • @AlJo so you were able to use jQuery in the contentScript then? As thats the only place it would work, and of course only place it would be useful (and this is what you were seeing in Google Chrome, as chrome only exposes the contentScript scope to you). – Noitidart Apr 11 '16 at 01:38

2 Answers2

1

Framescripts are not webpages and do not offer access to most of the global variables that jquery expects to exist, e.g. XHR, the document and window itself etc.

Even if you rigged the variables in a way that looks like a window environment this would still be highly problematic because a frame script has a lifetime that extends beyond that of a DOM windows, i.e. its existence is tied to a tab, not to individual pages of a tab. Jquery is designed to only live as long as a page does.

A third problem is security, framescripts run with chrome/system privileges and so would jquery if you ran it directly from a frame script. Jquery is not designed to be security-conscious as it is normally constrained by the same-origin policy of a website. Some complex interaction of event processing and XHRs might thus open security vulnerabilities.

So using jquery in browser-internal scripting environments is not recommended.

The two options of doing DOM manipulation from frame scripts is

a) Using standard DOM APIs directly from a frame script. Addon scripts automatically run with ES6 support enabled (e.g. destructuring, arrow functions etc.) and do not have to concern themselves with cross-browser compatibility. In other words: There's no need for jquery

b) If using jquery is absolutely necessary, e.g. because some 3rd-party library depends on it, then it's possible to create a sandbox with the current window as its prototype and using the subscript loader to inject jquery and a custom script into it.

Recommended way to create sandbox to isolate it from untrusted content and at the same time drop system privileges:

let options = {
  // this is the name reported in about:memory
  sandboxName: "<addon name> <purpose of sandbox>",

  // ensure that jquery sees the window as global
  sandboxPrototype: content,

  // reduces GC overhead by having the sandbox reside in the same space as target window
  sameZoneAs: content,

  // don't include components object that grants access to privileged APIs
  wantComponents: false, 

  // helper functions for interacting with untrusted content
  wantExportHelpers: true,

  // clean view of DOM APIs, otherwise untrusted content could override prototypes
  wantXrays: true,

  // addon ID, used by addon debugger and memory reporting
  // sdk addons can obtain it via require("sdk/self").id, other addons define it in the install.rdf
  metadata: {addonID: id}
}

// set the security principal to an extended principal covering the target window
let sandbox = Cu.Sandbox([content], options)

// structured-clone objects into the sandbox
sandbox.myData = {foo: "bar"}

loader.loadSubscript("resource://myaddon-id/libs/jquery.js", sandbox, "UTF-8")
loader.loadSubscript("resource://myaddon-id/src/mypagescript.js", sandbox, "UTF-8")

// call custom function created by mypagescript.js
sandbox.myFunc()

Note that the sandbox is only valid for the lifetime of a page, so if the frame gets navigated to a new window (content object) you will have to create a new sandbox


The above basically is the underlying low-level API used by the SDK's page-mod and webextensions content-scripts.

the8472
  • 40,999
  • 5
  • 70
  • 122
  • Thanks @the8472, but I find no documentation for the loadSubscript() function on the mozilla dev site. – AlJo Mar 29 '16 at 02:40
  • there is a link in my answer, if you actually read the prose instead of just copy-pasting code you might actually notice it. – the8472 Mar 29 '16 at 04:22
  • Always rude... @the8472, your code sample is interesting, but you don't answer the question... as to why frame scripts where designed with those limitations. Moz docs specifically say that frame scripts are for interacting with content, yet the frame script environment is inadequate for common scripting libraries. – AlJo Mar 30 '16 at 18:37
0

See my comments to your OP. The docs you read are not about content scripts. It is about framescripts and other elevated scopes. Google chrome does not have these elevated scopes. They ONLY have content script. This is why we were all confused.

This is how you use jQuery in your content scripts with jpm addon sdk.

Download the jquery lib into your data folder.

var tabs = require("sdk/tabs");
var mod = require("sdk/page-mod");
var self = require("sdk/self");

var pageUrl = self.data.url("page.html")

var pageMod = mod.PageMod({
  include: '*',
  contentScript: [self.data.url('jquery.min.js'), "console.log(jQuery);"]
})

This inserts jQuery into all websites. tabs.open(pageUrl);

If you use webextensions its the same exact way as google chrome: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/

Noitidart
  • 35,443
  • 37
  • 154
  • 323