2

I'm trying to import a .jsm file (from This github) called "WebSocketServer.jsm" in my Firefox extension. The situation in the follow:

  • The .jsm file is in a directory called modules with this path:

root_of_extension/modules/WebSocketServer.jsm

  • I've added to my chrome.manifest file this line:

resource external_components modules/

  • I've insert in my code the commend to import the file:

Cu.import("resource://external_components/WebSocketServer.jsm");

The problem is that from console I see the following error

console.error: 
Object
- message = Component returned failure code: 0x80070057 (NS_ERROR_ILLEGAL_VALUE) [nsIXPCComponents_Utils.import]
- fileName = undefined
- lineNumber = 6
- stack = @undefined:6:undefined|CuddlefishLoader/options<.load@resource://gre/modules/commonjs/sdk/loader/cuddlefish.js:129:9|run@resource://gre/modules
/commonjs/sdk/addon/runner.js:149:1|startup/<@resource://gre/modules/commonjs/sdk/addon/runner.js:113:7|resolve@resource://gre/modules/commonjs
/sdk/core/promise.js:118:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|then@resource://gre/modules/commonjs/sdk/core/promise.js:153:9|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:118:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|then@resource://gre/modules/commonjs/sdk/core/promise.js:153:9|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/
promise.js:185:11|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:118:11|then@resource://gre/modules/commonjs/sdk/core/
promise.js:43:43|resolve@resource://gre/modules/commonjs/sdk/core/promise.js:185:11|readAsync/<@resource://gre/modules/commonjs/
sdk/net/url.js:49:9|NetUtil_asyncOpen/<.onStopRequest@resource://gre/modules/NetUtil.jsm:137:17|
- toString = function () /* use strict */ toString

Line 6 in the "Cu.import" line. Do you have any ideas?

hasmet
  • 758
  • 3
  • 13
  • 32

2 Answers2

2

Just put it in your data folder than get the path like you would any other file in your data folder.

var {Cu} = require('chrome');
const self = require('sdk/self');    
Cu.import(self.data.url('modules/WebSocket.jsm'));

No need to mess with manifest I'm pretty sure.

Noitidart
  • 35,443
  • 37
  • 154
  • 323
  • using your code (declaring var self = require("sdk/self");) I have the following error: self.data is not a function – hasmet Jul 23 '14 at 08:10
  • Ok I looked it up, its `require("sdk/self").data.url("WebSocket.jsm")` I'm not sure why it's not a function, im not sdk guy. :( [MDN :: self module](https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/self) – Noitidart Jul 23 '14 at 08:53
  • unfortunately this solution also doesn't work :( thanks anyway – hasmet Jul 23 '14 at 09:44
  • 1
    You might want to upvote and/or accept (checkmark) answers that helped you. This is how you reward people spending time trying to solve your problems on this site ;) *Edit* Sorry. I missed that @Noitidart didn't get the `self.data.url` call right, so I'd agree this answer is only border-line helpful at best. – nmaier Jul 23 '14 at 14:01
  • Thx for vouch @nmaier! I was hoping the guy would figure it out :( You're nice guy you spoon feed me and everyone. We need to be better like that :( It looks like the problem even after I gave him the right version is he mis-spelled his own JSM file name.... wtf lol. Now thats frustrating, you expect ppl to figure out that much at the very least lol. I was doing `WebSocket.jsm` he should have fixed it to `WebSocketServer.jsm`.. Is that the only thing that was wrong after my 2nd comment to this solution? – Noitidart Jul 23 '14 at 21:23
  • @Noitidart, I've changed filename, but the difference is the path in wich is .jsm file. Your response, is helpful (infact I have upvoted it), but is wrong because the file had to be in "data" directory and not in "modules" directory. But, in general, I've accepted the response of nmaier because it is perfect. – hasmet Jul 24 '14 at 07:46
  • 1
    No problem I understand. I'm not upset about that. Just thought that from your topic post you were placing your modules in a modules folder. So I thought you moved the modules folder to the data folder. Now if modules folder was in your data folder yes you would have to do `.url('modules/Web....jsm')`. Now if you just moved the jsm out of the modules folder and pasted it into data folder then were still putting doing `.url('modules...`, thats on you :P haha but im happy that nmaier got the points cuz i owe him so much – Noitidart Jul 24 '14 at 08:06
1

Here is a solution I just tested.

First the structure:

$ ls -lR
total 8
drwxr-xr-x  3 maierman  staff  102 23 Jul 15:45 data
drwxr-xr-x  3 maierman  staff  102 23 Jul 15:47 lib
-rw-r--r--  1 maierman  staff  164 23 Jul 15:33 package.json

./data:
total 40
-rw-------  1 maierman  staff  17925 23 Jul 15:45 WebSocketServer.jsm

./lib:
total 8
-rw-r--r--  1 maierman  staff  874 23 Jul 15:47 main.js

Now, main.js:

const self = require("sdk/self");
const {Cc, Ci, Cu} = require("chrome");

const wssuri = self.data.url("WebSocketServer.jsm");

Cu.import(wssuri);

// Create an echo server
var clients = [];
var server;

exports.onUnload = function() {
  try {
    server.close();
    clients.slice().forEach(function(c) {
      try {
        c.close();
      }
      catch (cex) {
        console.debug("Failed to disconnect client " + client, cex);
      }
    });
  }
  catch (ex) {
    console.debug("Failed to disconnect server", ex);
  }
  Cu.unload(wssuri);
};

server = new WebSocketServer(12345);
server.onclient = function(client) {
  console.log(client + " connected");
  clients.push(client);

  client.onmessage = function(client, msg) {
    console.log(client + " message:" + msg);
    client.send(msg);
  };

  client.onclose = function(client) {
    console.log(client + " disconnected");
    clients = clients.filter(function(c) {
      return c != client;
    });
  };
};
server.connect();

Also make sure to get the lastest version of WebSocketServer.jsm. I just noticed and fixed a bug where client disconnection is not handled properly (but that is unrelated to your question).

And tested this by executing the following in a Scratchpad.

var ws = new WebSocket("ws://localhost:12345");
ws.onmessage = function(e) {
  console.log(e.data);
};
ws.onopen = function(e) {
  console.log("opened");
  ws.send("hello, world!");
};
ws.onerror = ws.onclose = function(e) {
  console.log(e.type);
};
nmaier
  • 32,336
  • 5
  • 63
  • 78
  • Please note that any kind of socket communication is unauthenticated. You'll want to add some authentication so that random websites and/or computers cannot call your "API". – nmaier Jul 23 '14 at 14:21
  • Yes, probably in the future the next two spets will be introduce some authentication and make fully asynchronous your code....I hope to do all without disturbing you on stackoverflow :) – hasmet Jul 23 '14 at 14:27