I wrote a cross-browser tab extension, but don't do that.

    A long, tedious intro with a claim to delusions of grandeur

    Once I discovered that something, as always, does not suit me much in this world. Namely, having entered some long query in a search engine on a desktop computer and then switching to a tablet, I could not recall the text of the query word for word in order to get exactly the same results. It all started so well. I saw in the search engine a link to the answer to my question and realized that it promises a long reading. Then I turned off the computer and flopped onto the sofa with the tablet with the thought that right now I’ll just reintroduce all of this into the search engine, open that link now on the tablet and lie down, calmly, in a more comfortable posture, read it ... But not here It was. Some minor discrepancies in the text - and my link is no longer in search results. To reproduce the link itself is also not an option: it is too long. Breaking head over the variants of the query text, I almost broke the tablet in fury. Damn it, I had to get up, turn on the computer again, start the browser and delve into the history to find the exact text of my query.

    Chrome and Firefox extension


    I thought, but it would be nice to write a browser extension that would allow you to transfer any of your open tabs through the server to any other computer and continue working with them there. Yes, in some browsers there is already a cloud function - you just need to log in to both devices and ... But that's the problem. And what if I have Chrome on my computer and Firefox on my tablet? And then ... Just log in, yeah. If I still remembered my Google account password. And I simply do not have an account in Firefox. I do not even know, are there any accounts at all? There are, of course, third-party cloud services, where you can register and probably somehow transfer the necessary link to yourself. But it’s still necessary to register there and firmly memorize another password ... No, this is absolutely not realistic. You can, in the end, throw yourself a link through the mail. But all this is long and save-paste from, and then into the address bar, which, for example, on the tablet is extremely inconvenient to do. No, all this is some sort of crap ...

    Lying on the couch, I slowly realized that all these actions require too many gestures ... No, guys, this will not work. And when I realize that something does not suit me in this world, then I sit down to write code to do everything in my own way. I thought that the social networks I am authorized on the tablet and on the desktop. And in different browsers, for example, on the same computer - too. In general, the solution for me was obviously to authenticate the user via social networks.

    Lyrical digression

    By the way, when I write something of my own, I also do it in my own way. I write in pure javaScript in an advanced notepad, I don’t use githubs, I don’t use third-party libraries, I don’t even use jquery. Therefore, there will be no tutorial on how to write a browser extension. I will not teach you this. Do not do as I do. I warn you - this is a bad example. I also want to say to all potential critics, anticipating their reaction - yes, I completely agree with all your righteous anger. Yes, you can not push the entire script into one or two files, but you have to chop everything up like a salad into many small pieces, so that it will then gather 3 hours along a long, clever command from the command line. Yes, you can not combine javascript-code and html-code in one file - it is better to screw another level of abstraction, which will combine them. Yes, You can't use tabular layout, but, damn it, it's iron! And, even more so - they will burn me now - you cannot use innerHtml and create a complex html structure in one fell swoop, but you need to attach and detach all children in a loop and diligently hang and then delete each handler ... Yes, I’m doing everything wrong. Sinful, I repent. But I do it consciously, because it's easier. And who will forbid me? In the end, it's not illegal, right? I do not know how to program as the modern fashion demands, and I don’t even want to try, because I think that the design of the development process is too complicated. I am for writing code with my hands, and not constructing it from someone else’s pieces, without writing a single line. However, my code is lightweight, it does not need to be collected by a special team and it works quickly. I write code using F5 technology. This is when in order to see at any time in the development process how the current version works, you just need to click in the F5 browser.

    However, I still had to hang up the handlers in the loop, because otherwise the extension fails validation. Also in extensions, just in case, in the index html file - suddenly - dynamically connected scripts are prohibited. Therefore, I connected them through the script tag.

    Tab storage

    So, I decided that the tabs opened in the browser should be saved in certain lists that will be called computers - Home computer, Work computer, Local computer. Local is when the list is not stored on the server, but in the browser database, and, accordingly, can be used only in the browser from which it is saved. This is for those tabs that do not need to flip between different computers. Well, the remaining lists can be viewed on any computers and browsers among the supported extensions.

    For each tab, the user can leave an arbitrary text comment. For example, it is convenient for me to remember which series I stopped while watching the series, as well as to mark for myself what is on the page, if by its title and the type of link it is not clear.

    According to the documentation for creating extensions for Chrome and Firefox, the extension code should be located in two files - the main one and the background one. The main script is engaged in displaying the interface for the user, and the background script can manage browser tabs and exchange data with the server. Managing tabs in Chrome and Firefox is very similar. For example, the event handler for opening or closing tabs in Chrome looks like this:

    chrome.tabs.onUpdated.addListener( function(tabId, changeInfo) {

    And in Firefox like this:

    browser.tabs.onUpdated.addListener( function(tabId, changeInfo, tabInfo) {

    And the function that will produce a list of all open tabs is written in the same way for both browsers:


    Yes, yes, chrome is also recorded in Firefox ... etc. It is a bit strange, however, very pleased that browsers are moving towards the standardization of their api.

    Actually, the entire expansion functionality is achieved by using several functions - open the extension window by clicking on its icon, read open tabs, close a tab, create a new tab, listen to tab events, exchange data with the extension window. Everything. These methods are available only from a background script.

    After reading the tabs opened in the browser are sent to my server and stored there in a normal SQL database. The server script is written in PHP. There is a user table that stores references to rows in another table — a data table. These data - and there are addresses of pages, their names and text comments of the user, stored in the format of text strings in a text field of length about a kilobyte. Data is stored unencrypted. About 1000 tabs can be saved per megabyte. For each user, a maximum of 25 such storages (“Computers”) are provided.

    However, the free version of the extension limits the user to two storages - the Home computer and the Work computer, and in each of them no more than 10 tabs can be saved. I still work on the paid version and payment methods. There will be up to 25 "computers" and up to about 1000 tabs in each, as well as a selection of background images, icons and names for each computer, hierarchical lists and much more.

    There is one more storage - Local computer. There are no restrictions here, since the tabs are stored in the browser’s local database on the user's computer. Here you can store as many tabs as you like, but no more than the hard disk allows. Moreover, since data is not stored in Local Storage, but in indexedDB, there is no limit of 5 MB or how many megabytes there. It is important not to accidentally clear this storage along with the history of the browser. I also plan to export and import tabs to a text file.

    To work with indexedDB, I wrote a small sublibrary of only 106 lines long. Unlike the database on the server, here all data is not required to be overtaken into a text string, but can be saved immediately in an associative array as is. The principle of storage there is this: the key - the value. And the value can be a huge associative array.

    User authentication


    Authorization, as I have already noted, occurs via social networks, and, on the server, using the OAuth protocol. While Facebook and VKontakte are supported, but I plan to increase the number of user authentication methods. The OAuth server authorization scheme is described in detail in the documentation for both social networks, so it makes no sense to dwell on it in detail. I will only note that I did not like the fact that during authorization a new browser tab opens, even if the user is already logged in to the social network and has already granted the right to expand. This tab has to be caught with a background extension script and then forcibly closed and in general, it does not look aesthetically pleasing, wedges in the other tabs and flashes when it appears and is destroyed.

    To close it, for VK you need to check the presence of the address in the tab event handler:


    And for Facebook:


    And just in case:


    Therefore, at first I sent to Google Web Store an extension assembly in which authorization was performed on the client with preliminary pull-up of the corresponding client javascript api social network. Moreover, since the extension is installed by the user, and I need to authorize on my server, I also pulled the html from my server in the background script of the extension in the I-frame, but already in it I pulled the social network api ...

    And the data exchange scheme with the server was like that. The index extension page sends the command (information about a click, for example) to a background extension script. A background script using postMessage sends data in i-frame html. I-frame sends the php data to the script on the server. The server responds in i-frame, i-frame responds to the background script, the background script responds to the index, the user sees the answer. Phew ... And most importantly - it all worked!

    In general, this is not a ride. Google wrapped up my extension with a number of formulations, among which was something vague about the fact that your extension doesn’t conform to our security policy. By correspondence with support, I managed to get things specific. Namely, they did not like the fact that the extension tightens up html and js from third-party servers ... In general, I had to be from client authorization and return to the server. Yes, sending an http post request from a background extension script directly to your server, however, turned out to be allowed. Well, okay. So even better. It turned out shorter and you do not need to pull the javascript api from social networks - this is too much waiting time for the user.

    View tabs

    Let's go back to the expansion options. The list of tabs itself is a series of lines, in which the favicon picture first comes, then the page title and, finally, the link. The fact that does not fit into the allotted size of the line on the screen is cut off. But in the database is saved completely. Also, any line can be carried up the screen in the form of colored tiles. This is for the most important sites that should be in front of your eyes first.

    List of tabs in Chrome

    The colors for the tiles are automatically selected based on the site's domain name. The function accepts url. The domain name is divided into three approximately equal groups of characters. The first characters from each group are converted into the values ​​of the color components: R, G, B. This conversion is performed as follows. The codes of these three characters are brought to the range d1, from 0 to 25, by taking the remainder of division by 26. Even the characters of the Russian alphabet will be brought to this range. It doesn’t matter that the 27th letter becomes the first there: we don’t need the color components of all the letters of the alphabet to be necessarily different, let them repeat. Then three received numbers from the range d1 (0 ... 25) are proportionally reduced to the range d2 (150 ... 255). In general, these ranges are set at the beginning of the function and can be changed to any other. I took 150 ... 255 so that the components of the color were bright. If you specify, for example, 0 ... 100, then the tiles will turn out dark. Thus, three characters from the domain name are converted to 3 numbers from the range 150 ... 255. And then, as you may have guessed, they are interpreted as components of the color of the R, G and B tile. Everything is very simple.

    getSiteColor=function(url) {
    	var d1=[0,25], d2=[150,255];
    	var code=0, codep=0, color=0, str='', domen='', ar=[], inc=0;
    	ar=url.split('//'); if (ar.length>1) {str=ar[1];} else {str=ar[0];};
    	if (str.length % 3 >0) {inc++;};
    	for (var i=0; i<str.length; i+=inc) {
    		code=str.slice(i, i+1).charCodeAt(0);
    		codep=code % (d1[1]-d1[0]+1);
    		color=Math.round( codep * (d2[1]-d2[0]) / (d1[1]-d1[0]) ) + d2[0];
    	return {r:ar[0], g:ar[1], b:ar[2], domen:domen};

    Html document structure

    An html document consists of several canvas elements with absolute positioning, combined by an overlay, and a div block in which the list is displayed. The resize browser window has a function that resizes all of these elements, adjusting them to the new height and width. There is also a minimum size, the overcoming of which causes the appearance of scroll bars. A background image is displayed on the bottom canvas. I decided that for different lists (that is, Computers) it is necessary to set different backgrounds to make it easier for the user to navigate. The background picture fills the window with preservation of its proportions and is slightly lightened so as not to over-focus attention on itself - a white translucent rectangle is drawn on top of it. Above the background canvas is the canvas of the main menu; it fills only the upper part of the screen. Well, even higher is the div block, in which the list of tabs is formed. Navigation on the canvas menu is carried out through my mini-library.

    Opera and Yandex browser


    On the main screen there is a checkbox, which, when clicked, switches between the Russian and English languages ​​of the interface. Here you can redirect the page to the same address, but with a parameter in the command line. This parameter is read before loading all other elements. And based on its value, this or that js-file with phrases in Russian or English is loaded into an associative array for phrases: lng_en.js, or lng_ru.js. And in the application itself, to output interface phrases, references to text strings from this associative array are used. Also, depending on the value in the address bar, the file containing the elements of the graphical interface, buttons: buttons_en.png, or buttons_ru.png, is loaded. I decided that it is better to create buttons right along with icons and inscriptions in each language in the graphical editor, rather than creating one empty button and overlaying text with icons and labels, especially since there are not many of them and this whole sprite sheet weighs only 50 Kb. I plan to continue to work on the design and make all the buttons different in shape.

    The general file with sprites main.png, which contains graphic elements that are not tied to a specific location, is loaded anyway.

    Web version

    I thought that it would be nice if the links carefully stored from the home or work computer could be viewed on the way from the phone. But not all mobile OS browsers support extensions. So I created a web build. By logging into the site at a specific address, you can still log in using one of the social networks and view your tabs.

    Yes, there is no possibility to add tabs to the list or edit. But you can at least open tabs from the list and view pages. I think it is worthwhile to work on the mobile version of this site and display tabs in it in a larger way.

    Web version in IE 11


    I didn’t do much to promote my expansion. Only created groups in social networks and invited all friends there. Yes, launched an advertising campaign in Yandex Direct for 1500 rubles. She didn’t give any special results, but maybe I’ve misplaced the ad. Or maybe the problem is that I indicated a link to the English version of the homepage of the extension. And, maybe, it was worth giving the link not to the homepage, but immediately to one of the expansion stores. As you understand, I am not a marketing genius. In general, I will try again with other parameters. The campaign gave 39 clicks. It is difficult to say whether I acquired some new users as a result.

    There was one oddity with the version under Firefox.

    Statistics for October 17 shows as many as 227 downloads. I don’t know whether the campaign in Yandex.Direct contributed to this or not, but then for some reason it’s again going to take 1-2 downloads per day. At the same time, for the Firefox extension there is the concept of daily users:

    Why downloads were 227, but the daily users remained only 1-2, it is not clear. Perhaps it was some kind of glitch. In general, I still didn’t understand what it was and where all these people were ... The

    statistics on the Chrome Web Store extension store pleased with some kind of forever non-loading schedule - what’s there, I never saw - and 5-10 daily users .

    Also, I sent the assembly to the Opera extension store. However, having laid out two versions and without waiting for the moderation of any of them, I at one point spat on putting fresh ones there. And, really, why it is necessary, if extensions from the Chrome shop are perfectly installed in the Opera.


    I created three build extensions - for Chrome, Firefox and the web version. Actually, all three builds are the same build, which simply indicates in the config which browser engine is being used at the moment. And the corresponding functions for working with tabs are initialized. I change this value before packing in zip and sending the package to the appropriate extension store.

    Versions for Chrome and Firefox have been tested and were posted in the respective official extension stores. Moreover, registration as a developer of extensions with Google costs $ 5. Mozilla is free. The web version of the extension is on the server. The build from the Chrome store works fine in compatible browsers: it can also be installed in Yandex Browser and Opera. I plan to release new versions with even more advanced features.

    In general, browser extensions are power. Now I do not need to get up from the couch, and also there is no need for rage to break the tablet. This is full Zen. All good.

    Also popular now: