CrossRider - How do I inject script to specific tabs? And how do I reload specific tabs?

468 views Asked by At

We are using CrossRider to develop an extension for Internet Explorer. We also have extensions for Chrome, Firefox and Safari, but we didn't use CrossRider for these extensions. I would like to know how we can inject a script to specific tabs in CrossRider? And after we do it, will it be injected also to tabs which will be opened later? And if yes, how do we remove the script so it will not be injected to any more tabs?

Here is the script, we have to add a case to CrossRider. Only in Safari we also remove the script, because in Chrome and Firefox it's not added to tabs which will be opened later. If it does in CrossRider then we have to remove it in CrossRider too.

Controller.showNotification = function() {
    var possibleURLs = /(mail\.google\.com|mail\.yahoo\.com|mail\.live\.com|mail\.aol\.com|mail\.rambler\.ru)/gi;
    var possibleURLsArray = ["http://mail.google.com/*", "https://mail.google.com/*", "http://*.mail.yahoo.com/neo/*", "https://*.mail.yahoo.com/neo/*", "http://*.mail.yahoo.com/mc/*", "https://*.mail.yahoo.com/mc/*", "http://*.mail.yahoo.com/dc/*", "https://*.mail.yahoo.com/dc/*", "http://*.mail.live.com/*", "https://*.mail.live.com/*", "http://*.webmail.aol.com/*/Suite.aspx", "http://*.webmail.aol.com/*/suite.aspx", "http://*.mail.aol.com/*/suite.aspx", "http://*.mail.aol.com/*/Suite.aspx", "http://mail.aol.com/*/suite.aspx", "http://mail.aol.com/*/Suite.aspx", "https://*.webmail.aol.com/*/Suite.aspx", "https://*.webmail.aol.com/*/suite.aspx", "https://*.mail.aol.com/*/suite.aspx", "https://*.mail.aol.com/*/Suite.aspx", "https://mail.aol.com/*/suite.aspx", "https://mail.aol.com/*/Suite.aspx", "http://mail.rambler.ru/mail/compose.cgi*"];
    var possibleURLsScriptURL = Utils.getUrl("content/src/common/show_notification_script.js");
    var possibleURLsScriptRelativeURL = Utils.getRelativeUrl("content/src/common/show_notification_script.js");
    switch (Sys.platform) {
        case 'chrome':
            chrome.tabs.query({}, function(tabs) {
                for (var i in tabs) {
                    if (tabs[i].url.match(possibleURLs) !== null) {
                        chrome.tabs.executeScript(tabs[i].id, {
                            file: possibleURLsScriptRelativeURL
                        });
                    }
                }
            });
            break;

        case 'safari':
            safari.extension.addContentScriptFromURL(possibleURLsScriptURL, possibleURLsArray, [], true);
            break;

        case 'mozilla':
            for (var i in tabs) {
                if (tabs[i].url.match(possibleURLs) !== null) {
                    tabs[i].attach({
                        contentScriptFile: possibleURLsScriptURL
                    });
                }
            }
            break;

        case 'crossrider':
            appAPI.dom.onDocumentStart.addJS({
                resourcePath: possibleURLsScriptRelativeURL,
                whitelistUrls: possibleURLs
            });
            break;
    }
};

Controller.disableShowNotification = function() {
    var possibleURLsScriptURL = Utils.getUrl("content/src/common/show_notification_script.js");
    switch (Sys.platform) {
        case 'safari':
            safari.extension.removeContentScript(possibleURLsScriptURL);
            break;
    }
};

Utils.getUrl = function(filename, preferSecure) {
    return WS.getURL(filename, preferSecure);
};

Utils.getRelativeUrl = function(filename) {
    return WS.getRelativeUrl(filename);
};

/* Function to retrieve the relative URL/URI of a file in the platform's file system. */
WS.getURL = function(filename, preferSecure) {
    if (typeof filename !== "string") {
        filename = "";
    } else if (filename.substr(0, 1) === "/") { /* Remove forward slash if it's the first character, so it matches with the base URLs of the APIs below. */
        filename = filename.substr(1);
    }

    switch (Sys.platform) {
        case 'mozilla':
            if (typeof exports === 'undefined') { // Means we're in a content script.
                return  self.options.extensionURL + filename;
            }
            return require("sdk/self").data.url("../lib/"+filename);

        case 'chrome':
            return chrome.extension.getURL(filename);

        case 'safari':
            return safari.extension.baseURI + filename;

        case 'web':
        case 'conduit':
            if (preferSecure && 'remote_secure' in WS.config.URLs.APIs) {
                return WS.config.URLs.APIs.remote_secure + filename;
            }

            return WS.config.URLs.APIs.remote + filename;

        case 'crossrider':
            filename = filename.substr("content/".length);
            if (filename.indexOf('png') !== -1) {
                return appAPI.resources.getImage(filename);
            }

            return "resource://" + filename;

        default:
            return '../' + filename; /* Added temporarily as a fix for Node.js compatibility */
    }
};

/* Function to retrieve the relative URL/URI of a file in the platform's file system. */
/* Currently this function is only defined for chrome and crossrider. */
WS.getRelativeUrl = function(filename) {
    if (typeof filename !== "string") {
        filename = "";
    } else if (filename.substr(0, 1) === "/") { /* Remove forward slash if it's the first character, so it matches with the base URLs of the APIs below. */
        filename = filename.substr(1);
    }

    switch (Sys.platform) {
        case 'chrome':
            return "/" + filename;

        case 'crossrider':
            filename = filename.substr("content/".length);
            return filename;
    }
};

And how do we reload specific tabs in CrossRider? Do we have to send a message to the tab which will reload itself? Or is it possible to reload tabs from the background?

Controller.reloadAllEmailTabs = function() {
    var possibleURLs = /(mail\.google\.com|mail\.yahoo\.com|mail\.live\.com|mail\.aol\.com|mail\.rambler\.ru)/gi;
    switch (Sys.platform) {
        case 'chrome':
            chrome.tabs.query({}, function(tabs) {
                for (var i in tabs) {
                    if (tabs[i].url.match(possibleURLs) !== null) {
                        chrome.tabs.reload(tabs[i].id);
                    }
                }
            });
            break;

        case 'mozilla':
            for (var i in tabs) {
                if (tabs[i].url.match(possibleURLs) !== null) {
                    tabs[i].reload();
                }
            }
            break;

        case 'safari':
            var browserWindows = safari.application.browserWindows;
            for (var i = 0; i < browserWindows.length; i++) {
                var safari_tabs = browserWindows[i].tabs;
                for (var j = 0; j < safari_tabs.length; j++) {
                    if (safari_tabs[j].url.match(possibleURLs) !== null) {
                        safari_tabs[j].url = safari_tabs[j].url;
                    }
                }
            }
            break;

        case 'crossrider':
            appAPI.tabs.getAllTabs(function(tabs) {
                for (var i = 0; i < tabs.length; i++) {
                    if (tabs[i].tabUrl.match(possibleURLs) !== null) {
                        appAPI.tabs.reload(tabs[i].tabId);
                    }
                }
            });
            break;
    }
};

Our Extension ID is 43889. I'm using Internet Explorer 11 but this extension should work on all versions of Internet Explorer.

Update: I added cases for CrossRider from Shlomo's answer, but they don't work (they don't do anything in CrossRider).

2

There are 2 answers

0
Shlomo On

Regarding appAPI.dom.onDocumentStart.addJS, this indeed injects the script on all pages that match whitelistUrls when they load and cannot be removed. If you need greater control over when to inject the script, you can use appAPI.tabs.executeScript in conjuction with appAPI.tabs.onTabUpdated and add a condition before injecting the script, something like:

var DoNotLoad = false; // Your condition for not injecting script
appAPI.tabs.onTabUpdated(function(tabInfo) {
    if (tabInfo.tabUrl.match(possibleURLs) !== null && !DoNotLoad) {
        appAPI.tabs.executeScript({
            tabId: tabInfo.tabId,
            code: 'alert("Running script");'
        });
    }
});
8
Shlomo On

If I understand your requirements correctly, they can be summarized as follows:

  1. How to inject a script to specific tabs?
  2. How to inject a script to new tabs?
  3. How to remove a script from injecting into any more tabs?
  4. How to reload a specific tab from the background?

Questions 1&2 can be handled using appAPI.dom.onDocumentStart.addJS specifying the whitelistUrls property as your possibleURLs, whilst 4 can be achieved using a combination of appAPI.tabs.getAllTabs, and appAPI.tabs.reloadTab.

As to question 3, I'm not quite clear as to why you would want to add and then remove a script as you have done for Safari, but if the intention is to simply prevent the script from running on Safari, you can specify condition using appAPI.platform around the code injection (see example).

As you will note, all this is achieved in the background scope as you require. If I have not understood correctly, please clarify each question and I will try to help.

[Disclosure: I am a Crossrider employee]

background.js:

appAPI.ready(function($) {
  // get's all open tabs
  appAPI.tabs.getAllTabs(function(tabs) {
    for (var i=0; i<tabs.length; i++) {
      // For tabs with matching URLs
      if (tabs[i].tabUrl.match(possibleURLs) !== null) {
        // Reload the tab
        appAPI.tabs.reloadTab(tabs[i].tabId);
      }
    };
  });

  // For browsers other than Safari
  if (appAPI.platform !== 'SF') {
    // Inject script on tabs with matching URLs
    appAPI.dom.onDocumentStart.addJS({
      js: "alert('hello world!');",
      whitelistUrls: possibleURLs
    });
  }
})