I had tried to install the latest version of Windows 10 (at this time 1909, the September 2019 version), but it had failed with a blue screen. I kind of ignored it, because I thought they will probably fix it or maybe it's because my laptop is new and so on. But recently I got this warning in Settings Windows Update: "You’re currently running a version of Windows that’s nearing the end of service. We recommend you update to the most recent version of Windows 10 to get the latest features and security improvements".

  So I tried to install it again. Same thing: a blue screen with a creepy smiley telling me it has failed to boot, with a stop code of "MEMORY MANAGEMENT" at FIRST_BOOT when BOOTing. Well, no shit, Sherlock! I tried to install it using the Media Creation Tool (which I recommend when you have Windows Update issues because you can download the update and save it into an ISO, so you can try it again and again without redownloading everything) and I got a more specific error: "0xC1900101 - 0x30017". What does it mean? No one knows, but it led me down a rabbit hole of people having a lot of different issues.

  This post will not discuss every single problem out there, you can search for yourself, I only wrote this because in some obscure corner of a forum I saw one person saying he solved by uninstalling Diskcryptor, a software that I had also installed, but never used. Once I uninstalled it, the update went without a hitch.

  So, summary:

  • if you have Diskcryptor, uninstall it. You can re-install it later.
  • download the Media Creation Tool for your service pack
  • tell it to download in an ISO file
  • mount the ISO and install from there
  • check what error you get
  • Google for it until you find someone having had the same specific problem

I am writing this post to let people know why a particular annoying problem happens on Windows 10 with regards to notifications. Before it was called "Focus Assist" it was called "Quiet hours" and you would turn it on to make annoying notifications not show while you were working or playing. After a Windows update, Microsoft renamed it to Focus Assist and turned it into a more complex setting, rather than on/off. But then the problems appeared.

Symptoms:
  • Notification traybar bubble is white (outline filled) and going over with the mouse it either says nothing or says "1 notification"
  • When you click on it, it shows no notifications and the bubble remains filled
  • If you right-click it, none of the options in the Focus Assist menu seem to be working and none are checked
  • If you go to Settings and click on Focus Assist, Settings crashes with no error message
  • You also may have Avast antivirus installed

People have been tracking the problem on this Microsoft forum: Settings app crashes accessing "Focus Assist" settings and here are our findings:

  1. The problem comes from Avast (or some other source) turning off the Windows Push Notifications User Service. Turning it on, restores Focus Assist functionality.
  2. Avast has something called Silent Mode, which many people use because Avast started pushing all these annoying messages lately
  3. In the Avast configuration (go to Menu , Settings, Components, scroll down the page until Performance, Do Not Disturb Mode, then Customize) there is a setting called "Silence notifications from 3rd-party apps". By default it's on. Turn it off and Avast will no longer kill the service
  4. If the cause of this behavior is different from Avast's silent mode, let me know. An immediate fix is to go to Services (services.msc), scroll down to Windows Push Notifications User Service (followed by underscore and some meaningless numbers and letters) and make sure it is started.


Hope this helps.

TLDR version:

0x80070643 is probably thrown when you don't have the right software version, in other words, the update is not for you. Sometimes you need to upgrade your software in order for it to apply. To fix the problem with SQL Server, try installing the SQL Server 2014 Service Pack 2 if you are still at SP1.

Now for the full version:

I thought the way Windows updates is a good thing. It keeps the computer up to date, regardless of how annoying it is to stop your work in order to perform updates. The problem, though, appears when having to perform an update that fails. Windows Update will nag at you again and again and again that you have updates. You don't have the option to ignore an update (unless you download a specific tool) so you are forced to solve any problem with the update. This is still a good thing, even if annoying. And if regular people that don't know how to solve issues like that are angered enough, it will also motivate Microsoft to test their updates better. Win, win. Unless it happens to you!

Anyway, this blog post is about KB4019099 or KB4032542 - Cumulative Update 13 for SQL Server 2014 SP1 which failed with a vague error code Error 0x80070643, which is met in several situations when trying to install stuff. In order to get to the bottom of the problem, I manually downloaded the installer for the update and tried again.

This time the error was clearer: TITLE: SQL Server Setup failure.
------------------------------

SQL Server Setup has encountered the following error:

The cached MSI file 'C:\WINDOWS\Installer\1bfcbd.msi' is missing.
Its original file is 'sql_engine_core_inst.msi' and it was installed for product 'SQL Server 2014 Database Engine Services' from 'F:\x64\setup\sql_engine_core_inst_msi\', version '12.1.4100.1', language 'ENU'.
To resolve this problem, recover the missing file from the installation media and start setup again.
For more information about how to resolve this problem, see 'Steps to restore the missing Windows Installer cache files' (http://go.microsoft.com/fwlink/?LinkId=144387) in the Microsoft Knowledge Base.

Error code 0x84B20002.

For help, click: http://go.microsoft.com/fwlink?LinkID=20476&ProdName=Microsoft%20SQL%20Server&EvtSrc=setup.rll&EvtID=50000&EvtType=0xD66F84B3%25400xF762992B%25401202%25402


Amazingly enough, the link that is supposed to solve the problem actually solves the problem. First of all the go.microsoft.com link causes too many redirects for Chrome, so you have to open it in some other browser. Once you do that, you reach this link: How to restore the missing Windows Installer cache files and resolve problems that occur during a SQL Server update and at the end you get a VBS script that seems to repair missing C:\Windows\Installer files from the original installation source.

The first thing the page says is to try setup.exe /ACTION=REPAIR /INDICATEPROGRESS=TRUE from the original installation source for SQL Server 2014, which of course you don't have anymore. But even if you do have it and you run the command, it fails near the end with a funny error: "C:\WINDOWS\Installer\1bfa87.msi" So the only possible solution is to run the VBS script. After that, the update install actually started.

... and failed with another error: The upgrade cannot be installed by the Windows Installer service because the program to be upgraded may be missing, or the upgrade may update a different version of the program. Verify that the program to be upgraded exists on your computer and that you have the correct upgrade.
Error code: 1642
. Why are you asking me to upgrade something if I don't even have the version you need?! I've tried the setup repair option, just to see if anything else changed since running FindSQLInstalls.vbs, but I got the same error.

Under the assumption that the "original installation source" is actually not enough - since there was a Service Pack 2 released since I've installed SQL Server from a kit, I've downloaded the SP2 file. Maybe it has a repair option. Ran it, and it ran successfully. Could it be that I never upgraded my SQL Server instance? Yes. Then all those "different version" messages actually make some sense.

Once I did that, Windows Update presented me with different updates altogether! Note that the original update said "SQL Server 2014 SP1" when executed.

Some of the updates installed OK, some failed, mainly Security Update for Microsoft Visual Studio 2010 Service Pack 1 (KB2645410) and Update for Microsoft Visual Studio 2010 Service Pack 1 (KB2635973). These are updates from 2012 and are related to the standalone VS version used by SQL Server Management Studio. I tried a restart, the updates remained there to annoy me. They both failed with error code 0x80070643 and when tried to install them manually they both reported the wrong software version.

Perhaps it is from all the meddling. Installing SP2 would have probably solved all the problems.

I hope it takes you less time to figure this out, once you've read this article.

Update: How to solve the issue of obsolete Visual Studio 2010 updates:

I've downloaded the Microsoft Fixit tool for forceful uninstall of software, even if the installer is not cached in C:\Windows\Installer. Then I uninstalled "Microsoft Visual Studio 2010 ENU". At this moment SQL Server 2014 Management Studio would not work anymore due to a missing component. Then I reinstalled Microsoft Visual Studio 2010 Shell (Isolated) Redistributable Package. At this moment SQL Server 2014 worked again. Then I ran Windows Update, which found several updates to download, including a Service Pack 1 and several others. Their installation went with only a hitch, a random 0x80246007 (BITS service) error that went away when I retried the update. I started Microsoft SQL Server 2014 Management Studio, just to be sure it worked, and it did. Finally.

Thus endeth the saga of the reluctant Windows Updates.

I've decided the functionality of the Bookmark Explorer extension was pretty close to final and, before I refactor it to a new form, I wanted to make sure it works for all the browsers that support the WebExtensions mechanism, mainly Chrome, Firefox and Opera. Frankly, I have no idea why anyone would use Firefox or Opera, but if you do, I've got great news for you: I have published the extension for all of them:
Haven't tested extensively, I am going to do that in the near future, but rejoice, now you can read your news at speed and comfort, then remove them from your bookmarks once you have grown tired. There are some changes to the extension that need to be addressed:
  • The most significant is changing the keyboard shortcut for "Previous Bookmark" to Ctrl-Shift-O for Firefox and Opera, because changing extension key shortcuts in Firefox is really difficult and Ctrl-Shift-K is already used by the developer tools
  • The default settings have been updated. Now, when you install the extension for the first time you will get:
    • 30 second wait for the "Read Later" links to autoclose, giving the browser time to cache the title and icon
    • Preload next tab is now true by default, leading to loading the content of the next news item while you read the current one
    • When creating bookmarks - from anywhere - their URLs will be stripped of some marketing bullshit
  • A lot of bug fixes and speed improvements went into this aparrently minor release

I also plan to make a video of how to use the extension, since letting users read the long description and figure out what the extension does didn't quite work :) I am considering changing the name of the extension for version 3 and I am open to suggestions. I am thinking of Bookmark Surf or something like this. Please let me know of any problems with the extension. I will fix bugs and I will write new features if I agree they are good for my users. All you have to do is ask!

Enjoy!

Update: I was so happy that Firefox for Android supports addons that I just installed it immediately and expected it to work. Unfortunately, the support for the Web Extensions API is very limited for the Android version, most importantly not having a bookmarks API, so the Bookmark Explorer doesn't work. I did make the extension more robust, though, by debugging it on the Android version.

Ever wanted to write a quick and dirty Javascript function that would get content from the web and do something with it, but you couldn't because of the pesky cross origin security limitations? Good Samaritans have created CORS proxies to help with that!

One of them is crossorigin.me, a completely free (and open source) proxy which can be used very easily. Instead of doing an AJAX request to http://someDomainYouDontOwn/somePage, you do it to https://crossorigin.me/http://someDomainYouDontOwn/somePage. And it works for any GET requests, as long as the Origin header is sent (browsers set it automatically for Ajax calls, but not for regular browser requests, so that why https://crossorigin.me/https://google.com will show Origin: header is required if you open it with a browser).

But there are other options, too. CORS Anywhere, CORS proxy and even using YQL are all valid, and that after just five minutes of googling around.

Of course, one might not want to depend on flimsy external free services for a production app, but it sounds perfect for the quick and dirty bastards like me.

I want to let you know about the latest features implemented in Bookmark Explorer.



The version number for the extension is already 2.9.3, quickly approaching the new rewrite I am planning for 3.0.0, yet every time I think I don't have anything else I could add, I find new ideas. It would be great if the users of the extension would give me more feedback about the features they use, don't use or want to have.

Here are some examples of new features:
  • Skip button - moves the current page to the end of the bookmark folder and navigates to the next link. Useful for those long articles that you don't have the energy to read, but you want to.
  • Custom URL comparison scheme. Useful for those sites where pages with different parameters or hash values are considered different and you get duplicate notification warnings for no good reason.
  • Duplicate remover in the Manage page. This is an older feature, but now the button for it only appears where there are duplicates in the folder and with the custom URL scheme it's much more useful.
  • Option to move selected bookmarks to start or end of folder, something that is cumbersome to do in the Chrome Bookmark Manager
  • Automatically cleaning bookmark URLs of marketing parameters. This is in the Advanced settings section and must be enabled manually. So far it removes utm_*, wkey, wemail, _hsenc, _hsmi and hsCtaTracking, but I plan to remove much more, like those horrible hashes from Medium, for example. Please let me know of particular URL patterns you want to clean in your bookmarks and if perhaps you want the cleaning to be done automatically for all open URLs

As always, if you want to install the extension go to its Google Chrome extension page: Siderite's Bookmark Explorer

The first thing that strikes anyone starting to use another IDE than the one they are used to is that all the key bindings are wrong. So they immediately google something like "X key bindings for Y" and they usually get an answer, since developers switching IDEs and preferring one in particular is quite a common situation. Not so with Eclipse. You have to install software, remove settings then still modify stuff. I am going to give you the complete answer here on how to switch Eclipse key bindings to the ones you are used to in Visual Studio.

Step 1
First follow the instructions in this Stack Overflow answer: How to Install Visual Studio Key Bindings in Eclipse (Helios onwards)
Short version: Go to Help → Install New Software, select your version in the Work with box, wait until the list populates, check the box next to Programming Languages → C/C++ Development Tools and install (with restart). After that go to Window → Preferences → General → Keys and change the Scheme in a dropdown to Microsoft Visual Studio.

Step 2
When Eclipse starts it shows you a Welcome screen. Disable the welcome screen by checking the box from the bottom-right corner and restart Eclipse. This is to avoid Ctrl-arrows not working in the editor as explained in this StackOverflow answer.

Step 3
While some stuff does work, others do not. It is time to go to Window → Preferences → General → Keys and start changing key bindings. It is a daunting task at first, since you have to find the command, set the shortcut in the zillion contexts that are available and so on. The strategy I found works best is this:
  • Right click on whatever item you want to affect with the keyboard shortcut
  • Find in the context menu whatever command you want to do
  • Remember the keyboard shortcut
  • Go to the key preferences and replace that shortcut everywhere (the text filter in the key bindings dialog allows searching for keyboard shortcuts)

You might want to share or at least backup your keyboard settings. No, the Export CSV option in the key bindings dialog gives you a file you can't import. The solution, as detailed here is to go to File → Export or Import → General → Preferences and work with .epf files. And if you think it gives you a nice list of key bindings that you can edit with a file editor, think again. The format holds the key binding scheme name, then only the custom changes, in a file that is what .ini and .xml would have if they decided on having children.

Now, the real decent thing would be to not go through Step 1 and instead just start from the default bindings and change them according to Visual Studio (2016, not 2005!!) and then export the .epf file in order for all people to enjoy a simple and efficient method of reaching their goal. I leave this as an exercise for the reader.

A short list of shortcuts that I found missing from the Visual Studio schema: rename variable on F2, go to declaration on F12, Ctrl-Shift-F for search across files, Ctrl-Minus to navigate backward ... and more to come I am sure.

I had this problem with Perforce where I accidentally Reconciled my offline work with all the files in /bin and /obj folders, resulting in a huge 6000+ file changelist. OK, simple one button mistake, surely there must be some one button undoing what I just did. It appears there is not.

In order to fix this I have to follow these steps:
  1. Change the settings of Perforce to show files even in changelists larger than 1000 items (the default value)
  2. Select by hand in the changelist window the files from obj and bin folders and using Revert on them
  3. Revert the few other files that were unwanted in the changelist, like .suo and .user files - note that Revert on added files doesn't delete them, it just unadds them
  4. Create a file with paths to ignore and then use p4 set P4IGNORE=<filename> for future reconcile work

What didn't work was adding a filename or path filter when visualizing the changelist, since that is a changelist filter, not a files filter. It will show you changelists that have files that contain the pattern, but not filter the files inside the changelists themselves.

For reference, the p4ignore file I used looked like this:
p4ignore
bin/Debug
obj/Debug
*.suo
*.user
Note that I also added the p4ignore file itself, although the file was not in any Perforce repository (yet).

"But, Siderite, you should use Git (or whatever source control is the newest fad at the moment)!" Wish that could, my friend, wish that I could.

Today the free antivirus Avast reported my BitTorrent installation as infected with Win32:Evo-Gen (Susp). It also promptly removed the executable of the program. I tried to reinstall it, also to have the same happen to the installation program. I've reported a false positive (I hope it is) for BitTorrent Stable (7.9.8 build 42577) and then I added *bittorrent* as an exclusion pattern in Avast. I could then reinstall the program, retaining all of the settings and torrents in the download list.

I am writing this post to rant against subscription popups. I've been on the Internet long enough to remember when this was a thing: a window would open up and ask you to enter your email address. We went from that time, through all the technical, stylistic and cultural changes to the Internet, to this Web 3.0 thing, and the email subscription popups have emerged again. They are not ads, they are simply asking you to allow them into your already cluttered inbox because - even before you've had a chance to read anything - what they have to say is so fucking important. Sometimes they ask you to like them on Facebook or whatever crap like that.

Let me tell you how to get rid of these real quick. Install an ad blocker, like AdBlockPlus or uBlock Origin. I recommend uBlock Origin, since it is faster and I feel works better than the older AdBlock. Now this is something that anyone should do just to get rid of ads. I've personally never browsed the Internet from a tablet or cell phone because they didn't allow ad blockers. I can't go on the web without them.

What you may not know, though, is that there are several lists of filters that you can choose from and that are not enabled by default when you install an ad blocker. One of my favourite lists is Fanboy's Annoyances list. It takes care of popups of all kinds, including subscriptions. But even so, if the default list doesn't contain the web site you are looking at, you have the option to pick elements and block them. A basic knowledge of CSS selectors helps, but here is the gist of it: ###something means the element with the id "something" and ##.something is the elements with the class name "something". Here is an example: <div id="divPopup" class="popup ad annoying"> is a div element that has id "divPopup" and class names "popup", "ad" and "annoying".

One of the reason why subscription popups are not always blocked is because beside the elements that they cover the page with, they also place some constraints on the page. For example they place a big element over the screen (what is called an overlay), then a popup element in the center of the screen and also change the style of the entire page to not scroll down. So if you would remove the overlay and the popup, the page would only show you the upper part and not allow you to scroll down. This can be solved with another browser extension called Stylish, which allows you to save and apply your own style to pages you visit. The CSS rule that solves this very common scenario is html,body { overflow: auto !important; }. That is all. Just add a new style for the page and copy paste this. 19 in 20 chances you will get the scroll back.

To conclude, whenever you see such a stupid, stupid thing appearing on the screen, consider blocking subscription popups rather than pressing on the closing button. Block it once and never see it again. Push the close button and chances are you will have to keep pressing it each time you visit a page.

Now, if I only had a similar option for jump scares in movies...

P.S. Yes, cookie consent popups are included in my rant. Did you know that you can block all cookie nagware from Blogspot within one fell swoop, rather than having to click OK at each blog individually, for example?

Just when I thought I don't have anything else to add, I found new stuff for my Chrome browser extension.

Bookmark Explorer now features:
  • configurable interval for keeping a page open before bookmarking it for Read Later (so that all redirects and icons are loaded correctly)
  • configurable interval after which deleted bookmarks are no longer remembered
  • remembering deleted bookmarks no matter what deletes them
  • more Read Later folders: configure their number and names
  • redesigned options page
  • more notifications on what is going on

The extension most resembles OneTab, in the sense that it is also designed to save you from opening a zillion tabs at the same time, but differs a lot by its ease of use, configurability and the absolute lack of any connection to outside servers: everything is stored in Chrome bookmarks and local storage.

Enjoy!

I have been plagued by this thing for a few weeks: every time I turn on the Wi-Fi, then turn it off, something starts turning the Bluetooth on. Turn it off and it goes back up in a minute. The only solution was to turn off the phone and then back again without turning Wi-fi or Bluetooth on. Strangely enough, there is no way to disable Bluetooth on the phone and no way to know who turned it on last.

As an investigation, I tried something called Event Logger, which logs when Bluetooth is turned on or off, but fails to notify you of what did it. In fact, I am still not sure how I was supposed to determine what software did it and this demonstrates a systemic issue with mobile phones: you have no real control or even knowledge over what happens in it.

Long story short, I've uninstalled a lot of applications just to see if the problem goes away. In the end it was Firechat! After uninstalling it, the problem went away. Apparently I am not the only one experiencing this, although one of the few pages on the Internet regarding Firechat and Bluetooth claims Firechat does not turn it on by itself, although numerous reviews on the app's Google Store page say differently.

Update 17 June 2016: I've changed the focus of the extension to simply change the aspect of stories based on status, so that stories with content are highlighted over simple shares. I am currently working on another extension that is more adaptive, but it will be branded differently.

Update 27 May 2016: I've published the very early draft of the extension because it already does a cool thing: putting original content in the foreground and shrinking the reposts and photo uploads and feeling sharing and all that. You may find and install the extension here.

Have you ever wanted to decrease the spam in your Facebook page but couldn't do it in any way that would not make you miss important posts? I mean, even if you categorize all your contacts into good friends, close friends, relatives, acquaintances, then you unfollow the ones that really spam too much and you hide all posts that you don't like, you have no control over how Facebook decides to order what you see on the page. Worse than that, try to refresh repeatedly your Facebook page and see wildly oscillating results: posts appear, disappear, reorder themselves. It's a mess.

Well, true to this and my word I have started work on a Chrome extension to help me with this. My plan is pretty complicated, so before I publish the extension on the Chrome Webstore, like I did with my previous two efforts, I will publish this on GitHub while I am still working on it. So, depending on where I am, this might be alpha, beta or stable. At the moment of this writing - first commit - alpha is a pretty big word.

Here is the plan for the extension:
  1. Detect the user has opened the Facebook page
  2. Inject jQuery and extension code into the page
  3. Detect any post as it appears on the page
  4. Extract as many features as possible
  5. Allow the user to create categories for posts
  6. Allow the user to drag posts into categories or out of them
  7. Use AI to determine the category a post most likely belongs to
  8. Alternatively, let the user create their own filters, a la Outlook
  9. Show a list of categories (as tabs, perhaps) and hide all posts under the respective categories
This way, one might skip the annoying posts, based on personal preferences, while still enjoying the interesting ones. At the time of this writing, the first draft, the extension only works on https://www.facebook.com, not on any subpages, it extracts the type of the post and sets a CSS class on it. It also injects a CSS which makes posts get dimmer and smaller based on category. Mouse over to get the normal size and opacity.

How to make it work for you:
  1. In Chrome, go to Manage Extensions (chrome://extensions/)
  2. Click on the Developer Mode checkbox
  3. Click on the Load unpacked extension... button
  4. Select a folder where you have downloaded the source of this extension
  5. Open a new tab and load Facebook there
  6. You should see the posts getting smaller and dimmer based on category.
Change statusProcessor.css to select your own preferences (you may hide posts altogether or change the background color, etc).

As usual, please let me know what you think and contribute with code and ideas.

I've written another Chrome extension that I consider in beta, but so far it works. Really ugly makeshift code, but I am not gathering data about the way I will use it, then I am going to refactor it, just as I did with Bookmark Explorer. You may find the code at GitHub and the extension at the Chrome webstore.

This is how it works: Every time you access anything with the browser, the extension will remember the IPs for any given host. It will hold a list of the IPs, in reverse order (last one first), that you can just copy and paste into your hosts file. The hosts file is found in c:/Windows/System32/drivers/etc/hosts and on Linux in /etc/hosts. Once you add a line in the format "IP host" in it, the computer will resolve the host with the provided IP. Every time there is a problem with DNS resolution, the extension will add the latest known IP into the hosts text. Since the extension doesn't have access to your hard drive, you need to edit the file yourself. The icon of DNS resolver will show the number of hosts that it wants to resolve locally or nothing, if everything is OK.

The extension allows manual selection of an IP for a host and forced inclusion or exclusion from the list of IP/host lines. Data can be erased (all at once for now) as well. The extension does not communicate with the outside, but it does store a list of all domains you visit, so it is a slight privacy risk - although if someone has access to the local store of a browser extension, it's already too late. There is also the possibility of the extension to replace the host with IP directly in the browser requests, but this only works for the browser and fails in case the host name is important, as in the case of multiple servers using the same IP, so I don't recommend using it.

There are two scenarios for which this extension is very useful:
  • The DNS server fails for some reason or gives you a wrong IP
  • Someone removed the IP address from DNS servers or replaced it with one of their own, like in the case of governments censorship

I have some ideas for the future:
  • Sharing of working IP/host pairs - have to think of privacy before that, though
  • Installing a local DNS server that can communicate locally with the extension, so no more hosts editing - have to research and create one
  • Upvoting/Downvoting/flagging shared pairs - with all the horrible head-ache this comes with

As usual, let me know what you think here, or open issues on GitHub.

Update 29 August 2017 - Version 3.0.4: The extension has been rewritten in EcmaScript6 and tested on Chrome, Firefox and Opera.

Update 03 March 2017 - Version 2.9.3: added a function to remove marketing URLs from all created bookmarks. Enable it in the Advanced settings section. Please let me know of any particular parameters you need purged. So far it removes utm_*, wkey, wemail, _hsenc, _hsmi and hsCtaTracking.

Update 26 February 2017: Version (2.9.1): added customizing the URL comparison function. People can choose what makes pages different in general or for specific URL patterns
Update 13 June 2016: Stable version (2.5.0): added Settings page, Read Later functionality, undelete bookmarks page and much more.
Update 8 May 2016: Rewritten the extension from scratch, with unit testing.
Update 28 March 2016: The entire source code of the extension is now open sourced at GitHub.

Whenever I read my news, I open a bookmark folder containing my favorite news sites, Twitter, Facebook, etc. I then proceed to open new tabs for each link I find interesting, closing the originating links when I am done. Usually I get a number of 30-60 open tabs. This wreaks havoc on my memory and computer responsiveness. And it's really stupid, because I only need to read them one by one. In the end I've decided to fight my laziness and create my first browser extension to help me out.

The extension is published here: Siderite's Bookmark Explorer and what it does is check if the current page is found in any bookmark folder, then allow you to go forward or backwards inside that folder.

So this is my scenario on using it:
  1. Open the sites that you want to get the links from.
  2. Open new tabs for the articles you want to read or YouTube videos you want to watch,etc.
  3. Bookmark all tabs into a folder.
  4. Close all the tabs.
  5. Navigate to the bookmark folder and open the first link.
  6. Read the link, then press the Bookmark Navigator button and then the right arrow. (now added support for context menu and keyboard shortcuts)
  7. If you went too far by mistake, press the left arrow to go back.

OK, let's talk about how I did it. In order to create your own Chrome browser extension you need to follow these steps:

1. Create the folder


Create a folder and put inside a file called manifest.json. It's possible structure is pretty complex, but let's start with what I used:
{
"manifest_version" : 2,

"name" : "Siderite's Bookmark Explorer",
"description" : "Gives you a nice Next button to go to the next bookmark in the folder",
"version" : "1.0.2",

"permissions" : [
"tabs",
"activeTab",
"bookmarks",
"contextMenus"
],
"browser_action" : {
"default_icon" : "icon.png",
"default_popup" : "popup.html"
},
"background" : {
"scripts" : ["background.js"],
"persistent" : false
},
"commands" : {
"prevBookmark" : {
"suggested_key" : {
"default" : "Ctrl+Shift+K"
},
"description" : "Navigate to previous bookmark in the folder"
},
"nextBookmark" : {
"suggested_key" : {
"default" : "Ctrl+Shift+L"
},
"description" : "Navigate to next bookmark in the folder"
}
}
}

The manifest version must be 2. You need a name, a description and a version number. Start with something small, like 0.0.1, as you will want to increase the value as you make changes. The other thing is that mandatory is the permissions object, which tells the browser what Chrome APIs you intend to use. I've set there activeTab, because I want to know what the active tab is and what is its URL, tabs, because I might want to get the tab by id and then I don't get info like URL if I didn't specify this permission, bookmarks, because I want to access the bookmarks, and contextMenus, because I want to add items in the page context menu. More on permissions here.

Now, we need to know what the extension should behave like.

If you want to click on it and get a popup that does stuff, you need to specify the browser_action object, where you specify the icon that you want to have in the Chrome extensions bar and/or the popup page that you want to open. If you don't specify this, you get a default button that does nothing on click and presents the standard context menu on right click. You may only specify the icon, though. More on browserAction here.

If you want to have an extension that reacts to background events, monitors URL changes on the current page, responds to commands, then you need a background page. Here I specify that the page is a javascript, but you can add HTML and CSS and other stuff as well. More on background here.

Obviously, the files mentioned in the manifest must be created in the same folder.

The last item in the manifest is the commands object. For each command you need to define the id, the keyboard shortcut (only the 0..9 and A..Z are usable unfortunately) and a description. In order to respond to commands you need a background page as shown above.

2. Test the extension


Next you open a Chrome tab and go to chrome://extensions, click on the 'Developer mode' checkbox if it is not checked already and you get a Load unpacked extension button. Click it and point the following dialog to your folder and test that everything works OK.

3. Publish your extension


In order to publish your extension you need to have a Chrome Web Store account. Go to Chrome Web Store Developer Dashboard and create one. You will need to pay a one time 5$ fee to open it. I know, it kind of sucks, but I paid it and was done with it.

Next, you need to Add New Item, where you will be asked for a packed extension, which is nothing but the ZIP archive of all the files in your folder.

That's it.

Let's now discuss actual implementation details.

Adding functionality to popup elements


Getting the popup page elements is easy with vanilla Javascript, because we know we are building for only one browser: Chrome! So getting elements is done via document.getElementById(id), for example, and adding functionality is done via elem.addEventListener(event,handler,false);

One can use the elements as objects directly to set values that are related to those elements. For example my prev/next button functionality takes the URL from the button itself and changes the location of the current tab to that value. Code executed when the popup opens sets the 'url' property on the button object.

Just remember to do it when the popup has finished loading (with document.addEventListener('DOMContentLoaded', function () { /*here*/ }); )

Getting the currently active tab


All the Chrome APIs are asynchronous, so the code is:
chrome.tabs.query({
'active' : true,
'lastFocusedWindow' : true
}, function (tabs) {
var tab = tabs[0];
if (!tab) return;
// do something with tab
});

More on chrome.tabs here.

Changing the URL of a tab


chrome.tabs.update(tab.id, {
url : url
});

Changing the icon in the Chrome extensions bar


if (chrome.browserAction) chrome.browserAction.setIcon({
path : {
'19' : 'anotherIcon.png'
},
tabId : tab.id
});

The icons are 19x19 PNG files. browserAction may not be available, if not declared in the manifest.

Get bookmarks


Remember you need the bookmarks permission in order for this to work.
chrome.bookmarks.getTree(function (tree) {
//do something with bookmarks
});

The tree is an array of items that have title and url or children. The first tree array item is the Bookmarks Bar, for example. More about bookmarks here.

Hooking to Chrome events


chrome.tabs.onUpdated.addListener(refresh);
chrome.tabs.onCreated.addListener(refresh);
chrome.tabs.onActivated.addListener(refresh);
chrome.tabs.onActiveChanged.addListener(refresh);
chrome.contextMenus.onClicked.addListener(function (info, tab) {
navigate(info.menuItemId, tab);
});
chrome.commands.onCommand.addListener(function (command) {
navigate(command, null);
});

In order to get extended info on the tab object received by tabs events, you need the tabs permission. For access to the contextMenus object you need the contextMenus permission.

Warning: if you install your extension from the store and you disable it so you can test your unpacked extension, you will notice that keyboard commands do not work. Seems to be a bug in Chrome. The solution is to remove your extension completely so that the other version can hook into the keyboard shortcuts.

Creating, detecting and removing menu items


To create a menu item is very simple:
chrome.contextMenus.create({
"id" : "menuItemId",
"title" : "Menu item description",
"contexts" : ["page"] //where the menuItem will be available
});
However, there is no way to 'get' a menu item and if you try to blindly remove a menu item with .remove(id) it will throw an exception. My solution was to use an object to store when I created and when I destroyed the menu items so I can safely call .remove().

To hook to the context menu events, use chrome.contextMenus.onClicked.addListener(function (info, tab) { }); where info contains the menuItemId property that is the same as the id used when creating the item.

Again, to access the context menu API, you need the contextMenus permission. More about context menus here.

Commands


You use commands basically to define keyboard shortcuts. You define them in your manifest and then you hook to the event with chrome.commands.onCommand.addListener(function (command) { });, where command is a string containing the key of the command.

Only modifiers, letters and digits can be used. Amazingly, you don't need permissions for using this API, but since commands are defined in the manifest, it would be superfluous, I guess.

That's it for what I wanted to discuss here. Any questions, bug reports, feature requests... use the comments in the post.