Showing posts with label add-on. Show all posts
Showing posts with label add-on. Show all posts

Monday, 17 January 2022

Running JavaScript Before Any Other Scripts On A Page

Injecting A Script At The Top Of Your HTML Page


By Strictly-Software

If you are developing an extension for either Firefox, Opera or Chrome, Brave, Edge, and Chromium, then you might come across the need to be able to inject some code into the top of your HTML page so that it runs before any other code.

When developing extensions for Chromium based browsers such as Chrome, Brave and Edge, you will most likely do this from your content.js file which is one of the main files that holds code to be run at certain stages of a pages lifetime.

As the Chrome Knowledge Base says the property values for the "run_at" property include;

  • document_idle, the preferred setting where scripts are guaranteed to run after the DOM is complete and after the window.onload event has loaded all resources which can include other scripts.
  • document_end, content.js scripts are injected immediately after the DOM is complete, but before subresources like images and frames have loaded. So after the DOM is loaded but before window.onload has finished loading external resources.
  • document_start, ensures scripts are injected after any CSS files are loaded but before any other DOM is constructed or any other script is run.  
  • There is of course the "run_at" property in the manifest.json file, which can be set to "document_start", to enable the codes running before other code does. This is especially useful if you need to change header values before a web page loads so that modified values such as the Referer or User-Agent can be modified. However, there may also be a need for you to set up an object or variable that is inserted into the DOM for code within the HTML page to access.

    For example in a User-Agent switcher where you need to both overwrite the Navigator object in JavaScript and the Request header, you may want to create an object or variable that holds the original REAL navigator object or its user-agent so that any page you may create yourself or offer to your users the ability to see the REAL user-agent, browser, language, and other properties if they wanted to.

    For example, I have my own page that I use to show me the current user-agent and list the navigator properties. 

    However, if they have been modified by my own user-agent switcher extension I also offer up a variable holding the original REAL user-agent so that it can be shown and compared with the spoofed version to see what has changed. I also have a variable that holds the original navigator object in case I want to look at the properties.

    Therefore my HTML page may want to inspect this object if it exists with some code on the page.

    // check to see if I can access the original Navigator object and the user agent string
    if(typeof(origNavigator) !== 'undefined' && origUserAgent !== null)
    {
    	// get the real Browser name with my Detect Browser function using the original Navigator user-agent
    	let realBrowser = Browser.DetectBrowser(origUserAgent);
    
    	// output on the page in a DIV I have
    	G("#RealBrowser").innerHTML = "<b>Real Browser: " + realBrowser "</b>";
    }

    This code just uses a generic Browser detection function for taking a user-agent and finding the Browser name. It even detects Brave by ruling out other browsers and if it is Chrome at the end I check for the Brave properties or mention of the word in the string, which they used to have but newer versions have removed it. 

    However there is hope in the community that they will create a unique user-agent with the word Brave in as at the moment people are having to do object detection which is the better method, and as Brave tries to hide, there are plenty of query strings and other API calls which can be made to find out whether the result indicates Brave rather than Chrome.

    However, at the moment, I am just using a simple detection on the window.navigator object that if TRUE indicates that it is actually Brave NOT Chrome. 

    A later article shows a longer function I developed with fallbacks in case the objects do not exist anymore as there used to be a brave object on the window e.g window.brave that no longer exists, so did many objects for Chrome such as window.google and window.googletag that no longer exist. However, this article explains all that.

    This is just the one line test you can do, it ensures it is not FireFox with a test for a Mozilla only object window.mozInnerScreenX and then checks that it is a Chromium browser with tests for window.chrome and that it's also webkit with a test for window.webkitStorageInfo before some tests for navigator.brave and navigator.brave.isBrave to ensure it's Brave not Chrome e.g:

    // ensure that a Chrome user-agent is not actually Brave by checking some properties that seem to work to identify the browser at the moment anyway...
    let isBrave = !("mozInnerScreenX" in window) && ("chrome" in window && "webkitStorageInfo" in window && "brave" in navigator && "isBrave" in navigator.brave) ? true : false


    However, this article is more about injecting a script into the HEAD of your HTML so that code on the page can access any properties within it.

    As my extension offers an Original Navigator object and a string holding the original/real user-agent before I overwrite it, then I want this code to be the first piece of JavaScript on the page.

    This doesn't have to be limited to extensions and you may have code you want to inject in the HEAD when the DOMLoads before any other code.

    This is a function I wrote that attempts to place a string holding your JavaScript into a new Script block I create on the fly and then insert before any other SCRIPT in the document.head.

    However, if the page is malformed, or has no defined head area it falls back to just appending the script to the document.documentElement object.

    If you pass false in for the 2nd parameter which tells the function whether or not to remove the script after inserting it then if you view the generated source code for the page you will see the injected script code in the DOM.

    The code looks within the HEAD for another script block and if found it inserts it before the first one using insertBefore() however if there is NO script block in the HEAD then the function will just insert the script into the HEAD anyway using the appendChild() method.

    An example of the function in action with a simple bit of JavaScript that stores the original navigator object and user-agent is below. You might find multiple uses for such code in your own work.

    // store the JavaScript in a string
    var code = 'var origNavigator = window.navigator; var origUserAgent = origNavigator.userAgent;";
    
    // now call my function that will append the script in the head before any other and then remove it if required. For testing you may want to not remove it so you can view it in the generated DOM.
    appendScript(code,true);
    
    // function to append a script first in the DOM in the HEAD, with a true/false parameter that determines whether to remove it after sppending it.
    function appendScript(s,r=true){
    
    	// build script element up
    	var script = document.createElement('script');
    	script.type = 'text/javascript';
    	script.textContent = s;
    	
    	// we want our script to run 1st incase the page contains another script e.g we want our code that stores the orig navigator to run before we overwrite it
    
    	// check page has a head as it might be old badly written HTML
    	if(typeof(document.head) !== 'undefined' && document.head !== null)
    	{	
    		// get a reference to the document.head and also to any first script in the head
    		let head = document.head;
    		let scriptone = document.head.getElementsByTagName('script')[0];
    
    		// if a script exists then insert it before 1st one so we dont have code referencing navigator before we can overwrite it		
    		if(typeof(scriptone) !== 'undefined' && scriptone !== null){	
    			// add our script before the first script
    			head.insertBefore(script, scriptone);
    		// if no script exists then we insert it at the end of the head
    		}else{
    			// no script so just append to the HEAD object
    			document.head.appendChild(script);
    		}
    	// no HEAD so fall back to appending the code to the document.documentElement
    	}else{
    		// fallback for old HTML just append at end of document and hope no navigator reference is made before this runs
    		document.documentElement.appendChild(script);
    	}
    	// do we remove the script from the DOM
    	if(r){
    		// if so remove the script from the DOM
    		script.remove();
    	}
    }
    



    I find this function very useful for both writing extensions and also when I need to inject code on the fly and ensure it runs before any other scripts by using a onDOMLoad method.

    Let me know of any uses you find for it.

    Useful Resource: Content Scripts for Chrome Extension Development. 


    By Strictly-Software

    Monday, 21 December 2009

    Add-On Support for Chrome

    Google Chrome Plugins

    Google Chrome has been my favourite browser for plain old web surfing since it came out but one of the few downsides to this fast loading and stable browser is the lack of support for add-ons. This is one of the reasons FireFox has claimed such a major stake in the browser market because there are literally hundreds if not thousands of add-ons available to extend the browsers functionality.

    Now Chrome has finally caught up and if you are subscribing to Googles dev channel you will be pleased to know that there are already a hundred or so add-ons waiting to be installed on your favorite browser. I have already installed Flashblock and Adblock and they seem to be working well. There does exist a web developer toolbar but its functionality is so cut down and basic at the moment its probably not worth getting.

    Now if you are like me and have been working around the lack of plugins for Chrome by using bookmarklets then you will be pleased with this news. However if you are still interested in using bookmarklets which will work cross browser then here is another good one. It allows you to download Flash videos from YouTube at a click of a button so that you can watch them later on.

    All you need to do is right click on the bookmarks bar (which should always be made visible) and then click "Add". Then in the Name you should put "YouTube Flash Downloader" or something similar and then for the URL you should paste in the following code:

    javascript:window.location.href = 'http://youtube.com/get_video?video_id=' + yt.getConfig("SWF_ARGS")['video_id'] + "&sk=" + yt.getConfig("SWF_ARGS")['sk'] + '&t=' + yt.getConfig("SWF_ARGS")['t'];



    This code has been updated to work with the recent changes in YouTubes API so don't worry as I know there is an old version of this bookmarklet floating around the web that doesn't work since November this year.

    Now when you are on YouTube and a video starts playing you can just click on that bookmark link and the video should start downloading to your computer.

    If you don't have a Flash player installed on your computer and want to play the FLV files in Windows Media Player then you can download an extension from the following location:


    If you are interested in other cool bookmarklets then check out my previous article which contained one for viewing the generated source code of a page and one for dynamic DOM inspection.

    Remember the cool thing about bookmarklets as apposed to add-ons is that they should work in all modern browsers as they are pure JavaScript. That even means IE 6!!

    Also before everyone gets carried away installing lots of add-ons for Chrome just take a step back and remember why you're using Chrome in the first place. For me its because FireFox, which I use for all my web development, has so many add-ons installed that its become very slow to load and many of the add-ons can cause slow page loads e.g Firebug or errors. Therefore if you're like me and use many browsers keep the add-ons to a minimum and keep your web browsing fast.

    I will shortly be writing an article about increasing speed and performance for all the major browsers but as a teaser I would give these pointers to quicker browsing.

    • Remove all add-ons that you never use anymore and disable those you rarely use.
    • Add-ons that will make your web surfing quicker such as FlashBlock, AdBlockPlus and NoScript are all good. Only enable those Flash movies and adverts if you really need to.
    • Turn off inbuilt RSS readers and use a special app if you require it.
    • Turn off all 3rd party cookies but keep Session cookies enabled.
    • Trawl through those preference settings and disable anything you do not use.
    • Disable link pre-fetching.
    • Regularly clear your cache, history and auto-complete data.
    Those are some very simple tips for increasing speed. I will go into more detail about the user preferences, http.pipelining, max-connections and TCP/IP settings another day.

    Tuesday, 1 December 2009

    Web Developer Browser Survery

    Browser Survey for Web Developers

    I have created a small survey aimed at web developers to gauge their opinions on the various browsers they use for developing and surfing the net. There are many great browsers out on the market and the browser that is best for development may not necessarily the one that is used for web surfing. For example I tend to do all my development in Firefox due to all the useful add-ons that are available for it such as Firebug, Web Developer toolbar and the Hackbar. However because of the number of add-ons its very slow to start and can be slow on loading certain pages. Therefore for pure web surfing I tend to use Chrome because its simple and quick.

    Please spend a few minutes to take part in this survey and let me know what you think.


    Take part in survey now

    Thursday, 20 August 2009

    Problems with IE 8 Developer Toolbar

    IE 8 Developer Toolbar Hanging and Locking Browser

    Update 25-Sep-09

    I have found that one of the primary causes of IE 8 hanging with the developer toolbar is its console logger. If you have a script that outputs messages to the console I have found that IE will hang until all the messages have been outputted to the console. The more messages you have the longer it takes. Also unlike Firebug which seems to output the messages during normal page load activity IE seems to cache all the messages and then output them all in one batch (or has the appearance of doing so). The CPU seems to max out during the outputting of these messages.

    I have been doing a lot of work lately with styles, fades and CSS which has obviously meant working with Internet Explorer building in code to handle the differences between IE and other browsers e.g getting computed styles from IEs currentStyle, Opacity differences etc. This has meant using trying to use the Developer Toolbar which was shipped as standard in IE 8.

    It should be a great add-on as it lets you do all the things Firebug has allowed developers to do for a long while including switching Javascript on/off, clearing sessions and cookies, viewing the DOM, inspecting elements and their styles and the ability to output debug to the console.

    However I have found that this developer toolbar add-on has a tendency to hang especially after the first use of it. I can go to a page and then open the developer window to change the browser or document modes or step through some debug. However if I minimise the window and go back to the main window and then try to open the developer window again the majority of the time it will refuse to come back to focus. Even if I try to maximise or restore the window or go to the desktop to find it. I have also noticed that when I do get focus back it will only partially be visible as if its trying to load content but struggling.

    In fact checking the Task Manager usually reveals a CPU of 50% or more. There will be two processes open one for the developer window the other for the main IE window but even though the developer window is hanging it seems the process with the high CPU is the browser window.

    I first thought it may just be some heavy Javascript code running on the page but I have had this problem with numerous sites and other people in the office have had similar issues.

    I don't know if this is common issue that developers have found but at the moment I am tending to use Firebug-lite or a custom DIV for outputting debug if I need to and custom pages for killing sessions and checking the current document mode and browser mode which are the 3 most common tasks I find myself doing which is a shame as I really like the layout and functionality the toolbar offers. Its just a shame that it seems to run very badly at the moment.

    Saturday, 15 August 2009

    The large number of duplicate frameworks

    Living with multiple frameworks

    I have just been investigating some of the source code that some of the new widgets I have added to my site lately contain. Its always good to delve into the source code of any widget or add-on as it helps you as a developer to see other ways of coding including methodology and style. Even with a compressed and packed source code you can easily reformat it to make it readable by using an unpacker tool like www.strictly-software.com/unpack-javascript.

    One of the things I noticed was the large amount of duplication in functionality that my site now has due to using these 3rd party add-ons and tools. There is no doubt that these widgets offer some great functionality with little or no cost and development time and they have enhanced the sites usability. However using Googles AJAX API, jQuery, add-this and snapshots and my own core library strictly.js I now have 5 separate JS files being loaded that handle events, load scripts dynamically and other various DOM manipulation functions.

    I don't know what the answer is as its too much to ask 3rd party developers to all develop their add-ons with one framework or to ask them to create multiple versions of their widget for each framework. Plus its very likely that any developer who creates a nice add-on will want to write their own code anyway as any coder worth their pay thinks they know best and in most cases they choose to encapsulate any helper functions into the add-ons core files.

    Now you could spend a lot of time creating local copies of these add-ons and rewriting all the code to share as much as possible but this would be futile and take a lot of effort. Plus every time a new version came out you would have to go through the same process or otherwise stay with an old version of the software.

    I was looking into a really nice looking lightwindow add-on the other day but this involved the installation of another 4 large Javascript files including Prototype and Scriptaculous. Therefore the dilemma was whether to add to the existing frameworks or rewrite the code to use JQuery instead.

    This started me thinking around the possibility of some sort of CDN which any developer could access and upload to that would hold files that met the requirements of a standardised API. Developers of new add-ons instead of recreating the wheel could build their widgets using these central objects. It would then be up to the site owner to decide which version of the object he wished to use but as long as any add-ons used on their site implemented this standard API the code would all work.

    For example thinking about the common need for event handling by all widgets. Say I am developing a new widget that shows previews of other sites (like the Snapshot add-on). Instead of writing new code to handle event management (add, remove, onload, DOM ready etc) I implement this standard API that has a specific naming convention. There can be multiple objects written to handle events on this CDN and they all differ in their internal workings but they all support the same interface and therefore it would be very easy for a developer to hook into them or change the core framework. An example would be that for any event object written to support this API to add an event they would follow this convention: element.addEvent(type,function,capture).

    The main framework developers would all have to standardise their naming conventions if they wanted to use the API but it would mean any site owner using multiple add-ons could choose one core framework for their sites engine and as long as all the add-ons and widgets were built to use the standard API it wouldn't matter if they changed the core framework from JQuery to Prototype the site would continue to work and without the need for code duplication. 3rd party widget developers could specify in their documentation which framework they felt the widget worked best with but it wouldn't depend on that framework and a site owner would make their choice without worrying about breaking the add-ons.

    It just an idea that I have just had and it would obviously need lots more thought and the support of the major framework developers as well as any 3rd party widget developers. However until the time comes when some sort of standardised central codebase is implemented and widely used it looks like code duplication and large files are here to stay. Therefore to mitigate this issue site owners will need to make sure all these files are optimised as much as possible through compression, minification, local hosting or CDNs, caching and other tweaks.

    This article is a great resource for covering this in detail: http://websitetips.com/optimization/

    Sunday, 5 April 2009

    Problems with Firebug and raised errors

    Firebug raising false errors or incorrect line numbers

    I have noticed recently that Firebug seems to be giving me unhelpful error reports and it seems to be happening more and more. By unhelpful I mean in the way Internet Explorer used to when an error was raised with an invalid or incorrect line number. I always thought Firebug was pretty spot on for error reporting but it seems that within the last month or so I have been getting quite a lot of errors in the console that say the problem is in file X and on line 120 but in fact after stepping through the problem the problem is actually in file Z and on line 45. Sometimes the error details that are reported in the console do not correspond exactly to those in the standard error console and a lot of the time errors that appear in Firebugs console do not appear in the standard error console.


    Possible Causes to spurious error messages

    Conflict with Firefox Add-Ons

    I have found problems in the past with certain Firefox add-ons that raise errors constantly or intermittently. One such add-on is the user-agent switcher which always raises a 
    UserAgentButton is null error and another add on which is a brilliant add-on for Search Engine Optimisation called the SEO Toolbar keeps raising the following error s4fToolbar_cache is undefined.

    Both of these errors disappear once the add-on has been disabled or in the case of the SEO toolbar you can turn it off without having to restart your browser. I have quite a number of add-ons on my work PC and due to my experience of errors related to add-ons I wouldn't rule out some sort of clash that is generating incorrect error details. 


    Syntax Problems

    I have found that sometimes when there are compilation errors usually due to missing or incorrect brackets then the error can be reported incorrectly. If a function hasn't been closed correctly due to a missing bracket then the calling function can sometimes be identified as the erroring function. However a large number of the errors I am getting invalid details for do not meet this criteria.


    Firefox or Firebug installations

    Within the last couple of months I have had upgrades of both Firefox and Firebug so it maybe that some problem within the application is causing the invalid error details.

    If anyone else has found similar issues recently with their Firebug installation it would be good to hear about it. As my colleagues also use Firefox and Firebug but without the various add-ons I have installed do not have these problems it means at the moment I am of the opinion the problem is most likely due to some sort of clash between add-ons as I cannot see such a problem not being spotted and resolved before any upgraded version of Firebug being released. I came to expect this sort of behaviour from IE and it was just understood by everyone that you couldn't get a proper error message when you needed one so its a tad annoying to say the least for me to start experiencing this issue with Firefox.