1

I am creating a Chrome Extension that would draw an image above tag showing Flash content. I have written the content script in my "contentscript.js" file which does nothing but simply inserts another script file "backgroundscript.js" into page's body via a script tag.

The code works on few of sites having flash videos and shows the image right above the Flash Player window but on other sites it does not show up. Also on few it shows up for a fraction of a second and then gets disappeared.

Below is my manifest file:

{
  "name": "My First Chrome Extension",
  "version": "1.0.0.0",
  "description": "Tag videos from websites with a single click!",
  "icons": {   "16":"application_16.png","48":"application_48.png","128":"application_128.png" },
  "homepage_url": "http://www.myurl.com",
  "page_action":{
                "default_icon":{
                "19":"application_19.png",
                "38":"application_38.png"
            },
            "default_title":"VDownloader browser plugin"

        },
  "content_scripts": [ { "js": [ "contentscript.js" ], "matches": [ "http://*/*" ], "run_at" : "document_end", "all_frames": true} ],
  "plugins": [ { "path": "myplugin.dll", "public": true } ],
  "manifest_version":2,
  "minimum_chrome_version":"17",
  "offline_enabled":true,
  "permissions":["tabs","http://*/*", "https://*/*","contextMenus"],
  "web_accessible_resources":["application.png","backgroundscript.js"]
}

Also I checked by inserting "debugger;" into my script and monitoring code execution via console; the script gets added at least once into the page body. Even in the cases where no image button is shown.

Is this some kind of anit-XSS control implemented on the the more advanced sites not showing my button?

I would really appreciate your help as I have been trying to get over this from past couple of weeks without success :(

EDIT:

Please see the content script below:

var s = document.createElement('script');
s.src = chrome.extension.getURL("backgroundscript.js");
s.onload = function() {
    this.parentNode.removeChild(this);
};
(document.head||document.documentElement).appendChild(s);

Target sites:

  1. Does not show the button: http://www.metacafe.com
  2. Shows the button for a moment: http://www.dailymotion.com
  3. Shows the button correctly: http://www.myreviewalarm.com

Please take a look at backgroundscript.js content:

var vdDelayTimer;
var vdUpdateInterval;
var playerButtons;

embedPlugin();

function embedPlugin() {
    var embed = document.createElement('embed');
    embed.setAttribute('type', 'application/x-myplugin');
    embed.setAttribute('id', 'myplugin');
    embed.setAttribute('style',   'width:1px;height:1px;position:absolute;left:0px;top:0px;');
    if(document.body!=null)
{
    document.body.appendChild(embed);
}
    testPlugin();
}

function testPlugin() {
    var plugin = document.getElementById('vdPlugin');
    if (plugin != null) {
        playerButtons = [];
        vdDelayTimer = setTimeout("appendButtons()", 2000);
    }
    else {
        window.alert('Plugin does not exist!');
    }
}

function updateButtons() {

    for (i = 0; i < playerButtons.length; i += 2) {
        updateButtonLocation(playerButtons[i], playerButtons[i + 1]);
    }
}

function updateButtonLocation(player, button) {

    var playerX = getX(player);
    var playerY = getY(player);
    var buttonHeight = 38;
    var buttonWidth = 196;
    var buttonX = playerX + player.offsetWidth - buttonWidth - 12;
    var buttonY = playerY - buttonHeight + 1;
    button.setAttribute('style', 'background-image: url(http://myurl.com/img/browser-download-button.png); width:' + buttonWidth + 'px;height:' + buttonHeight + 'px;position:absolute;left:' + buttonX + 'px;top:' + buttonY + 'px; cursor:pointer; cursor:hand;');
}

function appendButtons() {
    debugger;
    var objectTags = document.getElementsByTagName('object');
    for (var i = 0; i < objectTags.length; i++) {
        var objectTag = objectTags[i];
        if ((objectTag.hasAttribute('classid') && objectTag.getAttribute('classid') == 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000')
|| (objectTag.hasAttribute('type') && objectTag.getAttribute('type') == 'application/x-shockwave-flash')) {
            if (objectTag.offsetWidth >= 320 && objectTag.offsetHeight >= 240)
                createButton(objectTag, getX(objectTag), getY(objectTag),  objectTag.offsetWidth);
        }
    }
    var embedTags = document.getElementsByTagName('embed');
    for (var i = 0; i < embedTags.length; i++) {
        try {
            var embedTag = embedTags[i];
            if (embedTag.hasAttribute('type') && embedTag.getAttribute('type') == 'application/x-shockwave-flash') {
                if (embedTag.offsetWidth >= 320 && embedTag.offsetHeight >= 240)
                    createButton(embedTag, getX(embedTag), getY(embedTag), embedTag.offsetWidth);
            }
        }
        catch (err) { }
    }
    var videoTags = document.getElementsByTagName('video');
    for (var i = 0; i < videoTags.length; i++) {
        try {
            var videoTag = videoTags[i];
            if (videoTag.hasAttribute('src')) {
                if (videoTag.offsetWidth >= 320 && videoTag.offsetHeight >= 240)
                    createButton(videoTag, getX(videoTag), getY(videoTag), videoTag.offsetWidth);
            }
        }
        catch (err) { }
    }
    vdUpdateInterval = setInterval("updateButtons();", 500);
}

function createButton(videoTag, playerX, playerY, playerWidth) {
    debugger;
    var buttonHeight = 38;
    var buttonWidth = 196;
    var buttonX = playerX + playerWidth - buttonWidth - 12;
    var buttonY = playerY - buttonHeight + 1;
    var vdPlugin = document.getElementById('vdPlugin');
    var strLocation = window.location.toString();
   // if (isSupported(strLocation)) {
        var downloadButton = document.createElement('img');
        downloadButton.setAttribute('title', 'Tag this video');
        downloadButton.setAttribute('src', 'http://myurl.com/img/browser-download-button.png');
        downloadButton.setAttribute('style', 'background-image: url(http://myurl.com/img/browser-download-button.png); width:' + buttonWidth + 'px;height:' + buttonHeight + 'px;position:absolute;left:' + buttonX + 'px;top:' + buttonY + 'px; cursor:pointer;cursor:hand;z-index:2147483647;');
        downloadButton.setAttribute('onclick', 'javascript:document.getElementById(\'vdPlugin\').downloadNow(window.location.href);');
        downloadButton.setAttribute('oncontextmenu', 'javascript:return false;');
        document.body.appendChild(downloadButton);
        playerButtons.push(videoTag, downloadButton);
   // }
}

function getY(oElement) {
    var iReturnValue = 0;
    while (oElement != null) {
        iReturnValue += oElement.offsetTop;
        oElement = oElement.offsetParent;
    }
    return iReturnValue;
}

function getX(oElement) {
    var iReturnValue = 0;
    while (oElement != null) {
        iReturnValue += oElement.offsetLeft;
        oElement = oElement.offsetParent;
    }
    return iReturnValue;
}


function isSupported(url) {
    var regLen = supportedSites.length;
    var regEx;
    var res = false;
    try {
        for (var i = 0; i < regLen && res == false; i++) {
            regEx = new RegExp(supportedSites[i], "i");
            res = regEx.test(url);
        }
    }
    catch (ex) {
    }
    return res;
}
  • 1
    What are URL's of sites `it does not show up` and `it shows up for a fraction of a second and then gets disappeared.?` Do you have any custom scripts running to counter the `content scripts` job? – Sudarshan Dec 21 '12 at 04:35
  • The issue is probably in `contentscript.js` or `backgroundscript.js`. **Edit the question to include those.** You should also link to a target page that exhibits the problem. Finally, if the page uses or switches to SSL, that `matches` will not trigger for it. – Brock Adams Dec 21 '12 at 10:10
  • @Sudarshan: The sites I am trying to modify are not mine and hence I can not be sure if such a strategy as to counter the content scripts has been adopted by them or not. But lets suppose if such a functionality exists, then how to detect this and make an antidote :) – Furhan Shabir Dec 21 '12 at 13:27
  • Thanks for adding the one set of code, but we still need `backgroundscript.js` **If, and only if,** that is the complete content script, then `contentscript.js` does not appear to be a problem, but you should remove the `s.onload` code just in case. – Brock Adams Dec 21 '12 at 14:41
  • @BrockAdams: there you go. But I still believe that somehow the injected script is getting deleted after a while for some strange reason. – Furhan Shabir Dec 21 '12 at 14:57
  • One reason to remove that `s.onload` code . – Brock Adams Dec 21 '12 at 14:59
  • That code has `var plugin = document.getElementById('vdPlugin');`, but the `` it created has the id `myplugin`. Anyway, the function `updateButtons()` appears to be a/the problem. It looks like it's overrunning arrays. Can't test the code, because don't have the required plugin. Consider making a [Short, Self Contained, Compilable, Example](http://sscce.org/). – Brock Adams Dec 21 '12 at 15:12
  • 1
    I'm probably missing something but why are you injecting another script from content script? You can display the button from your content script that is sandboxed and can't be removed by scripts on the page. – Konrad Dzwinel Dec 21 '12 at 15:12
  • 1
    Also you are polluting the global space in background.js, other scripts may override your functions and change your variables. Put everything you can in self-executing anonymous function or a namespace. – Konrad Dzwinel Dec 21 '12 at 15:15
  • @BrockAdams: I am not sure why you think updateButtons() is overrunning the array and why would this be a problem only for few sites and for others it works alright :) – Furhan Shabir Dec 21 '12 at 15:16
  • @KonradDzwinel: I had tried it both ways ,i.e, creating button directly from Content Script and placing button generation code in a separate file. I got this notion from following post http://stackoverflow.com/questions/9515704/building-a-chrome-extension-inject-code-in-a-page-using-a-content-script – Furhan Shabir Dec 21 '12 at 15:22
  • But, is there any reason for injecting `background.js` from content script? Are you using variables from other scripts on page, or something like that? If not, then don't do it - you are just complicating the whole solution. – Konrad Dzwinel Dec 21 '12 at 15:27
  • @KonradDzwinel: The background.js needs to access page DOM to detected tags and get its attributes. I believe this could be done directly from content script as well. What do you say? Thanks – Furhan Shabir Dec 21 '12 at 15:33
  • 1
    Yes it can. Definitely get rid of `background.js` and move your code to content script. This may or may not solve your problem, but this is a right thing to do here. – Konrad Dzwinel Dec 21 '12 at 15:36
  • `updateButtons()` overruns the array because it if there are an odd number of `playerButtons`, say 5, it will try to get an illegal index, [5] in our example. The `for` loop and `playerButtons[i + 1]` is very poor code. But the problem will only show on sites with an odd number of buttons. – Brock Adams Dec 21 '12 at 15:49
  • @BrockAdams: When members into playerButtons[] are pushed, it is guaranteed that the array always contains Even number of elements. Please see createButton() where members are being pushed into playerButtons[] in pairs. "playerButtons.push(videoTag, downloadButton);" – Furhan Shabir Dec 21 '12 at 16:49
  • Okay, then that code is not overrunning the array (for now). You should still correct it so that future side-effects do not cause it to start doing so. – Brock Adams Dec 21 '12 at 16:57

0 Answers0