Feeds:
Posts
Comments

Posts Tagged ‘extensions’

Prelude : My blog has been silent for quite some time. I was busy with my Masters thesis for couple of months. I am starting with my PhD , wrapping up things and slowly getting into the groove. I hope to settle into a routine where I have one long blog post per week. Let us see how it goes !

    Nautilus is one of the most commonly used file manager for GNOME. One of the reasons for its popularity is its extensible architecture that allows developers to write scripts to customize it. Even if you are a command line person, extending Nautilus will result in dramatic increase in productivity. In this post, I will discuss the multiple ways in which Nautilus can be extended and the relative merits in each approach.

    The first step in extending Nautilus is to find the set of actions that are tedious (atleast not straightforward) – Tasks that need additional clicks or switching to terminal to get completed. The next step is to determine if there are command line tools available to automate the task or the task can be completed by additional code – Again since you are extending Nautilus, the task involved has to relate to files or folders. For eg, opening a file as administrator is a "relevant" task but starting a nuclear war from Nautilus is not !

Informally, it is easy to extend Nautilus if your task falls in the following categories : Adding new entries in context menus (or in toolbar) that involve selected files/folders or current folder, add additional custom properties to files and display those details in list view, modify the properties page to display additional tabs with information etc. There are other possibilities but these are the most common ones.

    If the above discussion sounds very abstract let us give some examples :
1. Open a terminal in the current folder or open the selected file as root.
2. Selecting a few audio files and adding them to Rhythmbox "Now Playing" queue.
3. Selecting a few files and sending them to thunderbird for attachment
4. Display IMDB details about the selected movie file in the property page etc.

The above examples show a gradient of use cases in the order of complexity. Some of them are so simple that they can automated using simple means. Tasks like (4) are tricky and need powerful tools. Selecting the right tool is important and we will discuss how to select the best approach.

Different Approaches to Customize Nautilus Context Menus

Like everything in Linux, there is always a variety of ways to customize Nautilus ranging from simple to complex. In this post, we will discuss the three most common approaches :
1. Using tools like nautilus-actions
2. Using Nautilus scripts
3. Using extensions written in nautilus-python

As before, all my discussion will be focused on Ubuntu but it should be relatively easy to apply to other Linux distributions.

Customizing Nautilus context menu using  nautilus-actions

This is probably the easiest method. All you need to know is the shell command or script to perform the task. Nautilus actions provides an intuitive GUI to decide on the filters and the actions to be performed. This approach works best if the following conditions are met :
a. the task you want to be automated is easily translatable in command line
b. the command line utility accepts the arguments in a relatively simple form (eg space separate arguments etc)
c. The command line utility depends only on information pertaining to the selected file/folder.

To install the package, type the following at terminal (or install this package from Synaptic) :
   

sudo apt-get install nautilus-actions

Once the package is installed it can be accessed at System -> Preferences -> Nautilus Actions Configuration. I will only give a basic discussion here as there is a decent tutorial on how to create a new action at How To Add Custom Functionality To Nautilus.

Let us take a simple example – If I right click on a folder , I want a new menu which says, "Open Terminal Here" and when it is clicked, a new terminal must be opened and the working directory of the terminal must be the selected folder. The first step is to find if it can be expressible in a "single" command. Find the name of the command to invoke the terminal – it is called gnome-terminal. Read the man page to find that it accepts an argument "–working-dir". When provided, it starts the terminal in specified folder.

Now start the Nautilus Action from System -> Preferences -> Nautilus Actions Configuration . The steps are :
a. Create an action.
b. In "Action" tab, give the action some name and select "Display item in selection context menu". If you want it to be visible in the toolbar, it can done too ! Select "Display item in toolbar" and choose some icon.
c. In the command tab, give "gnome-terminal" as path and parameters as "–working-directory=%d/%f". The %d and %f are special codes that will be expanded when the command is invoked. To see other special codes and what they mean, click on the "Legend" button.
d. In "Conditions" tab, select "Only Folders".

Now open a new Nautilus window , select a folder and right click. Presto ! You will see a "Open Terminal Here" menu. Select it and you will see a new terminal open with the selected folder as its current directory !

Some Notes On Nautilus-actions

You can take a look at Nautilus-actions project page to find lot of actions that automate your common tasks. To include them in your system, download the schema and then import them. To import, Tools -> Import assistant -> select the schema file. There are literally hundreds of nautilus actions that you can use immediately.

Nautilus Actions is a very nifty GUI tool that makes creating context menus dramatically easy. The best part is that specifying the command and filters is very intuitive. I will say that for a vast majority of scenarios, Nautilus actions is all that is needed to automate some task. But the simple nature of the tool is also its biggest enemy – there are some tasks that are slightly more complex and nautilus action is not very useful in them. A simple example will be a task which needs two commands to complete. Consider task (2) above – Adding selected mp3 files to Rhythmbox queue. The problem here is that if the file is not already in the library, Rhythmbox will not add them to the queue. So this needs two commands – one to add them to library if not already present and then add them to queue. Tasks like this are tricky to implement using Nautilus actions.

Another class of tasks that are not solvable using Nautilus actions is the ones that have tricky input formats. If you go the "Command" tab and click on "Legend" button, you can see that the list of special codes available are limited. They satisfy majority of needs but not all. Let us take a simple example , say task (3) – send selected files to thunderbird as attachment. Thunderbird has a command to compose a new mail with attachments but the arguments must be "comma" separated. In this case you are out of luck with Nautilus actions and must look at more powerful tools.

Nautilus Scripts

Nautilus has an extensible architecture that allows scripts to be executed. There is usually a misconception that Nautilus scripts has to shell scripts. That is no longer the case. Nautilus allows you to run scripts written in any language as long as they are executable and it knows which program to invoke. This means that you can write scripts in shell , python, perl or any other language as long as the first line of the script says which program Nautilus will have to invoke to execute the script (ie the shebang line).

You can consider that Nautilus actions provides a convenient wrapper over Nautilus scripts .The statement is not exactly true , but it is a good start. Before discussing Nautilus scripts, let us compare the two approaches – Nautilus script allows you to do certain things that are not possible in Nautilus actions. For eg, you can have a huge shell script with multiple lines that gets executed instead of a single command. In my opinion, another important advantage is that it is possible to invoke a Nautilus script without selecting a file – For eg one that runs using just the current folder information. This is not possible in Nautilus actions. On the down side, scripts are always available. It is not possible to show a Nautilus script for only mp3 files or only for local files. Another issue is that Nautilus scripts are most useful for local files and folders. For remote files (eg ftp , smb or webdav) they are essentially useless – but Nautilus action based commands will work fine in this scenario.

How to write Nautilus Scripts

All the Nautilus scripts are in the folder $HOME/.gnome2/nautilus-scripts . You can access them in command line or by File -> Scripts -> Open Scripts folder. Alternatively, you can right click on a file/folder and select Scripts->Open Scripts folder from the context menu. Note that the scripts menu will be available only if you have some scripts in that folder.

To write a new script, create a file in $HOME/.gnome2/nautilus-scripts and change its permissions so that the "user" has executable permissions. Make sure that you have a shebang line which tells Nautilus which program to invoke to run this script. If you want to organize your scripts then create subfolders in the nautilus-scripts folder. All the subfolders become sub menus in the Nautilus context menu.

When your script is invoked by Nautilus , at the most 4 environmental variables will be set by it. They are NAUTILUS_SCRIPT_SELECTED_FILE_PATHS, NAUTILUS_SCRIPT_SELECTED_URIS, NAUTILUS_SCRIPT_CURRENT_URI and NAUTILUS_SCRIPT_WINDOW_GEOMETRY. NAUTILUS_SCRIPT_SELECTED_FILE_PATHS and NAUTILUS_SCRIPT_SELECTED_URIS are newline delimited variables about the selected files. The only difference is that one gives the name of the directory and other gives it as a URI. ie for a local file /home/blah/abc.txt , the first variable will /home/blah/abc.txt  and second will give file:///home/blah/abc.txt . NAUTILUS_SCRIPT_CURRENT_URI gives the URI of the current location.

You can immediately see that the information available is pretty limited. You have to write the script using only these variables. The information is available as environment variables in shell script. For other languages, you may have to use additional modules to access them. Once you have written a script, it is time to test it ! The steps are :

a. Open a terminal and type "nautilus -q". This will close all instances of Nautilus.
b. Type "nautilus –no-desktop" . This is very useful when you are developing the script as it open Nautilus without opening your profile or preference data reducing the chance of data corruption.
c. Right click on a file/folder. You will notice that a new "Scripts" menu comes up and it has your script as the submenu. Selecting it will run your script with the options. You can alternatively run the script from File -> Scripts.
d. If you want to run a script without running on any specific file/folder, invoke the script using File -> Scripts. You must note that in this case only NAUTILUS_SCRIPT_CURRENT_URI will have meaningful value.

Debugging Tips for Nautilus Scripts

It is possible that your scripts may not work the first time. There are no easy way to debug the scripts. Here are some ideas that I find useful :

Case 1 : The script does not appear in Scripts menu (or the scripts menu itself does not occur)
1. Have you placed your script in $HOME/.gnome2/nautilus-scripts ?
2. Does it has executable permissions atleast for the user ?

Case 2 : The script appears in the menu but does not seem to work correctly
In this case, the bug is most likely in the logic of the code. Comment your entire script logic except the shebang line. Add few lines to echo the values of the environmental values into some file in say /tmp/blah. Quit nautilus and open it up. Execute the script. This will result in the arguments being dumped into the log file. Now manually set the environmental values with the values in log file and try executing the script from command line. Since we have the values of the environmental variables, we can simulate Nautilus execution from command line. Most likely , this will allow you to find the issue and fix it.

Notes on Nautilus Scripts

A huge list of Nautilus scripts are available at g-scripts page . Download the file
nautilus-scripts.tar.gz . Even though the information available to scripts are limited, many of them use shell commands in innovative ways. For eg, they use gdialog or zenity to show information graphically. Browse through the scripts to get an idea of what is possible using Nautilus scripts.

Nautilus scripts brings certain advantages and disadvantages. On one hand, they allow more complex actions to be performed. They are not limited to have only single command like Nautilus actions. They also can be executed without selecting any files. But the information available to the scripts is very limited – only 4 environmental variables. Also they are not useful when you invoke on remote files. It is also not possible to show the script only to files with selected attributes (eg only audio files). Of course, you can always return prematurely for files not matching your criteria but it is unnecessary work that must be repeated for all files.

Nautilus Extensions

Nautilus extensions can be considered as the Swiss army knife of customizing Nautilus. They have a relatively steep learning curve but once you learn them , you can extend Nautilus in ways that are simply not possible using other approaches. Nautilus extensions allows you to do tasks that are made possible by previous approaches and more . Some of the things that are possible are :

a) Adding menus for files/folders with certain attributes.
b) Adding new menus in toolbars.
c) Adding new custom attributes to files and folders and using them do perform special actions. It is also possible to display them in the detailed view. A simple example is to add say length of song for mp3 file and show it as a column in Nautilus.
d) Add new tabs in the property page – eg show additional IMDB information for movie files.
e) Add additional information about current location near the location bar.

The classical way to write extensions is in C. But gnome programming in C is bit tricky. I will not discuss them as there are easier ways available. If you are still interested , you can take a look at the Nautilus extensions API reference provided in the Notes section. You will have to compile your extension code and put the executable in /usr/lib/nautilus/extensions-2.0/ .

A cleaner and much easier alternative is to use Nautilus-Python . Nautilus-Python by itself is a C extension for Nautilus. What it does internally is that it exposes a "nautilus" module which can be used by Python programs to write Nautilus extensions in Python. The extension is quite well designed and provides a pythonic interface for programmers. To install this package,

    sudo apt-get install python-nautilus

Nautilus Python Interfaces

1. nautilus.ColumnProvider – This allows your program to give additional columns (attributes) for files in the current location when the user is in List mode. Usually gets the information supplied by nautilus.InfoProvider . An example is to show length of the audio for mp3 files.
2. nautilus.InfoProvider – This file is called on all files that the user is currently viewing. You can add new attributes to the files , add new emblems or perform other tasks. An example is to provide track details about the current audio file.
3. nautilus.LocationWidgetProvider – This allows some widget to appear near the location bar. I cannot think of any practical example for this interface.
4. nautilus.MenuProvider – Allows you to provide custom menus for the selected files or folders. It is also possible to create toolbars or background menus.
5. nautilus.PropertyPageProvider – Allows you to augment existing property page (Right click -> Properties) with additional pages displaying specific information about the selected file. An example is to show MD5 of a file or show IMDB details for a movie file.

Writing Nautilus Python Extensions

You can write Nautilus extensions in Python using the Nautilus-Python extension. The scripts you write has to be placed in $HOME/.nautilus/python-extensions. If you have admin rights, you can also place them at /usr/lib/nautilus/extensions-2.0/python-extensions. Usually I prefer my scripts to be in my home folder.

The development process is very similar Nautilus scripts. The steps are :

1. Create a python file in $HOME/.nautilus/python-extensions .
2. Extend one or more of the interfaces and code the relevant functions in the interfaces.
3. Make the script file as executable.
4. Kill all instances of Nautilus using "nautilus -q" . Note that many web pages asks you to use "killall nautilus" but I prefer my apporach as it allows nautilus to die gracefully 🙂
5. Restart Nautilus. During development, using "nautilus –no-desktop" as it starts without reading profile preferences.
6. Test your extension. This will be extension specific due to the various capabilities of the nautilus python extensions.

A Closer Look at Nautilus Python Extensions

As discussed above, Nautilus Python exposes 5 interfaces. Based on your needs your class will inherit from one or more of the interfaces. Each interface will have few methods where the logic of your extension has to be included. After installation , you can take a look at /usr/share/doc/python-nautilus/examples/ for working examples. You can even copy them to $HOME/.nautilus/python-extensions and play around with them till you are comfortable. If you want to see all the functions that the interfaces expose, un-gzip the file /usr/share/doc/python-nautilus/examples/documentation.py.gz. This will produce a file documentation.py which provides the signature and basic information about the methods exposed by the interfaces. Let us take a brief look at them :

1. nautilus.ColumnProvider – It exposes a single function get_columns . This function has to return a sequence of nautilus.Column objects. As an example, the extension can return information like runtime or codec details for an mp3 file.
2. nautilus.InfoProvider – Exposes a single function update_file_info with a file as an argument. The function can update the file in various ways – for eg, it can set new custom attributes, change emblem or perform other actions on the file.
3. nautilus.LocationWidgetProvider – Exposes a single function get_widget . The function returns some gtk widget which will be displayed near the location bar.
4. nautilus.MenuProvider – Probably the most used interface. It exposes three functions : get_file_items, get_background_items and get_toolbar_items . The first two functions determine the entries that appear in the context menu. The difference is that get_background_items is usually called for a folder. The last function is used for toolbar items hence you must name the icon parameter of the menuItem.
5. nautilus.PropertyPageProvider – Exposes get_property_pages function where you reture one or more "pages" or tabs. An example is to create a new "IMDB Details" page which shows the movie information.

Debugging Nautilus Python Extensions

Debugging Nautilus Python extensions is pretty tricky. The main reason is that the "nautilus" package that is used extensively in the code is available only when the script is invoked from Nautilus. But all is still not lost. The following are some of the tips I learnt when I built my library of Nautilus extensions 🙂

Case 1 : You wrote a code for new entries in context menu but it either does not appear or works incorrectly 
1. Is your script in $HOME/.nautilus/python-extensions ?
2. Is the script has its executable bit turned on?
3. Did you restart Nautilus ? (using nautilus -q and nautilus –no-desktop )
4. Check if the file is compiled in extensions folder – basically is there a .pyc file ? If not invoke the file with python to find the syntax error.
5. Import the logging module and check if the relevant functions are called.
6. If you think the menu is being shown incorrectly, then make sure you are using the relevant functions on the FileInfo class. The class has multiple utility functions and deciding the correct one is important.

Case 2 : You wrote a new property page and it does not appear
Try steps 1-5 from Case 1.
6. Check if all the widgets are visible (ie show method is called).
7. Check if the GUI that you try to render works normally. This can be done by moving the code that returns a page to another python file and putting the HBox/VBox into a gtk.window.

Notes On Nautilus Python Extensions

A good discussion about developing the extensions is at Nautilus Extensions. The discussion is primarily for C. A good C API reference can be found at Nautilus extensions API reference. For Python, nautilus-python Reference Manual provides a basic reference.

The reference manuals per se are very skimpy in details. The best way to learn how to code nautilus python extensions is looking at existing code. There are lot of excellent python extensions that you can use for learning. The simplest is the examples provided with the python-nautilus package. The files can be accessed at /usr/share/doc/python-nautilus/examples/ for working examples. To test them copy to $HOME/.nautilus/python-extensions , restart
nautilus using commands provided above. Nautilus pyextensions contains few useful scripts. Download the source code that is available as nautilus-pyextension-<version>.tar.gz file and play around with them. One of the most powerful examples for using Nautilus Python is RabbitVCS. You can take a look yourself at the amazing RabbitVCS screenshots. You can download the source using apt-get source command.

Generic Nautilus Debugging Tips

    I found some websites that mention an alternate way to debug Nautilus extensions. It did not work for me but I will mention it here for the sake of completeness.  Create a file called nautilus-debug-log.conf in your home folder with the following lines :

    [debug log]
    max lines=1000

If Nautilus crashes for some reason, it supposedly writes into the file nautilus-debug-log.txt. If it works for you then great ! You have access to another debugging tool 🙂

Summary and Tips on Choosing the correct Approach

There are three approaches to extend or customize Nautilus. Using Nautilus actions, scripts or extensions. Each of them have their own pros and cons.

1. There is a high likelihood that some one else had a similar problem before. So before choosing one of the approaches, check if the code is available somewhere. Check the discussion (notes section) above for good resources.
2. Is your task very simple? Can it be completed with a single command line utility? Then use the Nautilus actions.
3. Try to complete your task as much as possible using Nautilus actions even if it involves some thing quick and dirty. Most of the case, you are the only person going to use it. One important thing to note is that the command that you provide in Nautilus action can also be your own script !
3. If your task primarily involves invoking multiple command line utilities , needs only basic information about the files and applicable only for local files then use Nautilus scripts.
4. If the task needs execution of multiple commands but need to be used only for certain files (eg only for txt files) , then try to write a script which invokes the appropriate commands. It should able to massage the inputs $* or $@ appropriately. Then use this script as the command to be invoked in Nautilus actions and use the filters to apply it to certain files.
5. If you need to invoke scripts even without selecting any items and the input needed is simple, then use scripts. If more complex processing is needed using extensions.
6. If you need to show the option in toolbar , then use extensions (and implement get_toolbar_items function)
7. If your task is complex – adding attributes to files, adding additional columns , adding new property pages etc use extensions.
8. Using Nautilus scripts does not mean your app is confined to text only. Use gdialog, zenity in Shell scripts for data entry and basic UI. If you use other languages, use the gtk library to develop complex UI. For eg, I have a script that queries opensubtitles.org site for subtitles and shows the result in a gtk window. Selecting one of the results downloads the subtitle file locally.
9. If you are very comfortable with Python, skip scripts and use extensions.

Sample Nautilus Python Extensions

I have a large library of actions, scripts and extensions. In this post, I want to share two of them.

1. Send file to thunderbird as attachment : The task is to select a set of files and compose a mail in Thunderbird with the selected files as attachment. Almost all the scripts / extensions that I see in the net did not work correctly and hence I wrote it myself. This extension will work for single or multiple files. It will appear only if all the selected items are files. It assumes Thunderbird is located at /usr/bin/thunderbird (View File) .

2. IMDB Details Property Page : I wrote this extension as an exercise to learn property pages. It uses the excellent IMDbPY library to fetch details from IMDB. It works only on video files and strips the common unused characters before querying IMDB. Since this was a test, I blindly select the first result and show the details. This extension also uses other gtk widgets to have a more complex UI. Assumes you have IMDbPy and pygtk installed (View file) .

I hope the article showed how to improve your productivity by customizing Nautilus to perfectly suit your work style. If you have any additional tips or ideas please post them in comments !

Advertisements

Read Full Post »

[Update Nov 15 2011] : Chrome Nanny is now Nanny for Google Chrome. It also has a new home. The link to Google Chrome extension gallery is https://chrome.google.com/webstore/detail/cljcgchbnolheggdgaeclffeagnnmhno . Please spread the word !

 Chrome Nanny is a leech block like extension for Chrome. I developed it as I started using Chrome extensively and there was no leech block like extension for it. It has been kinda successful beyond my expectations – Almost 2000 people are using it ! I have been for the last couple of months with my masters and did not add any features. Now that I am free I thought, I will add a page which will show the features that are in the works and also provide a way to request new features.

I plan to make this page a single location where you can see the features that are being developed and also to request/discuss new features. Till the end of August 2010, I plan to have a weekly development cycle and after that probably once in two weeks – assuming there are some features to develop.

If you are interested in sending your patches , please email me to saravananDOTthirumuruganathanATgmailDOTcom.  The latest code can always be got from the repository here .

 

[Last Update] Update Jul 24 2011

Suggestions

One of the pain points is the initial setup. Chrome Nanny starts enforcing blocking behavior immediately after blocksets are created. If you make a mistake and you want to fix it, you have to enter the challenge text. Is there a heuristic that prevents challenge till the entire initial setup is done? ie I want to balance usability with the Chrome Nanny’s default behavior for productivity.

 

Features : In the next release

Vlad,Mathias : It is too easy to add a Whitelisted URL to the list. It can be done anytime, even when “You should be working”
I suggest to add the same check: if(chrome.extension.getBackgroundPage().BackGroundManager.checkIfBlockSetShudBeBlockedNOW(blockSetName)) challengeUser(blockSetName,’E’); to the function addUrlToWhiteList()

Jason : Perhaps it should be clear that the blacklisted sites are automatically tracked? Or perhaps the whitelist should just be a list of sites to track in addition (since isn’t the blacklist supposed to act like a whitelist too?)

Catherine : I have a suggestion, though. It would be nice if you had a feature that blocks ALL websites except those that the user specifies or puts in the whitelist–like the “Nuclear Mode” in StayFocusd.

Saravanan : Add purge option to Stats

Scott Allen : The main feature I miss, though, is a quick/easy way to block a site. What would it take to have a "block this" bookmarklet? Right now, I have to go through 3-4 mouse clicks, and then either copy/paste the URL or type it in. I’d like a one-click "Block domain" and maybe another "Block URL" one. After all, the whole point is to improve productivity, right? 🙂
Discussion : When you click on the Chrome Nanny’s icon page, it will have an option to block the domain/url. Clicking on it will take you to the options page. Also have a link to go to options page directly and for lock down.

Saravanan
Stricter time validation .
Mustafa :
Add the option to hide the blocked sites but show the allowed remaining time for the other ones. 2 reasons behind it:
-Everytime I see that blocked list I wanna disable the add-on and visit the sites. -I want to be able to see how many minutes do I have left for the restricted sites.

Anonymous : Add an option to password protect viewing Chrome Nanny options

Features : In the near future

Marko, Rajiv, anonymous : I would only echo what has already been brought up, that when you first start Chrome, it will let you see a site that you have blocked.  For example, I have blocked Facebook for certain hours during the day, but even during those hours, when you first start Chrome, Facebook pops up and you can see it until you click somewhere on the screen.  Then the Chrome Nanny block page shows up.  Still love it!  Just maybe a little hole to fix 🙂

Jim,Ben and many others :    Have a block behavior similar to leechblock.  I know leechblock as the option of limiting my facebook usage to 30 minutes ONLY on saturdays, and to block it every other day of the week . Is there a way to add that onto this extension? I really need it to help me out, because even 15 minutes everyday is too much for me at this point.

David T : It would be cool to be able to block a site based on the number of visits. I spend way too much time checking gmail to see if there are any new messages. Even though I’m only briefly at the website because there are no messages, it’s interruptive when I should be focusing. It would be cool to limit gmail to 2 or 3 visits per day, but be able to stay there and write emails if I’ve actually received something.

        
Tianyi Cui :        I propose a feature to use a custom JavaScript function to determine whether a website should be blocked.

        The parameters of the user-input function are an URL and some statistics about this URL (e.g. The logged time intervals of that domain in previous 24 hrs). I’m not sure how much statistics should be calculated and provided to balance configurability, performance and the time to implementation. I’ll think about it later and we can discuss. The statistics should be calculated only if needed (i.e. the parameter is a function) since probably most time we only need the URL and current time. The return values of the JS function can be either “Block”, “Don’t Block” and “Pass” (i.e. let the default rules to determine).

        This is an advanced feature which can be extremely useful for programmers (I bet a significant part of users are), as they can easily implement the feature they want by themselves, and the customized rules as JS function can be easily backed up, version controlled, and shared as it’s just plain text.

        I would like try to implement this feature by myself since I’m an experienced programmer. I don’t know JS very much and haven’t implemented browser extensions before. But it’s a great experience to hack and learn.

        Please comment on this idea and tell me which part of the source code I should read and modify and any suggestion on the implementation. 
         
Tianyi Cui :
        The challenge test should be prompted after user clicked “Save URL” (not after user clicked “Edit”) if and only if the edit could make a previously blocked URL not blocked any more (e.g. user is deleting URLs or reduced Block Time). When user is just adding URLs or increase Block Time or edit Tags, she should not be forced to the challenge test.
               
Brian :
        From: http://xkcd.com/862/

        “After years of trying various methods, I broke this habit by pitting my impatience against my laziness. I decoupled the action and the neurological reward by setting up a simple 30-second delay I had to wait through, in which I couldn’t do anything else, before any new page or chat client would load (and only allowed one to run at once). The urge to check all those sites magically vanished–and my productive computer use was unaffected.”

        I wonder if such a feature could be added to Chrome Nanny? Instead of blocking pages, make them load slowly?
 
Greg :
        A suggestion: When I’m on a site that is being timed, the Chrome Nanny icon should change — ideally it should be very dramatic (like all bright red) so I will notice that I am using up my time.  That would be a good warning not to stay on the site too long.  (This would also help when I leave a tab in the background that is eating up my time.)
thanks!

 

Bevans : Could you give us a way to change when a new "day" begins? Right now, it’s set at midnight of course, but I sometimes work until 1 or 2 AM, and if I’m using a site at midnight I begin using up the next day’s time. I’d like to be able to set it to reset the timers at 3 or 4 AM instead of midnight.

Lukasz : Personally I like the "StayFocused" behaviour in this regard where you get icon that changes from blue to red if the current site is on the list and then counter once there is less than a minute left. It’s clear indication I’m on a site I shouldn’t and that the time is ticking 😉

Saravanan : Implement notifications feature. (http://blog.chromium.org/2010/05/desktop-notifications-now-available-to.html)
Discussion : Notifications are a cute little feature. It would be nice to warn users that they have only for eg : say 5 minutes left. (Should this be made configurable ? )

sarah : Suggestion: If I block, for instance, http://www.example.com, your extension also blocks http://www.differentexample.com, presumably because you strip it to "example\.com" and add a wildcard up front to ".*example\.com" This is really bad – you’re blocking a completely separate domain, when you probably just wanted to block "same.example.com" You could try using a url parser library to get the actual domain name. Thanks for an awesome extension!
Discussion : Good observation ! The current behavior was intentional so that user enters only "google" to block all of google’s websites.  One possible compromise is to check if the block url resembles URL closely – If so block only the URL. If it is a substring/regexp, use the default behavior.

Ryan : add idle state task to roadmap – refer : http://code.google.com/chrome/extensions/trunk/idle.html

Patrick,Allen : i think that websites should be able to appear in multiple block sets so that they can be blocked at different times on different days (eg. I want to block a website in a specific time period during the week, but in a different one on the weekends.) leechblock, on firefox, provides this option
Discussion : Another change that might result in major design changes. Depending upon the demand, will make the decision.

Firefly,Adam,Michael :     Is it possible to implement the export / import feature from Leechblock? I have an extensive list of sites (about 150) that I use in firefox. I use this list across machines and I’d like to be able to use it in chrome nanny.
Discussion : If there is additional demand , will develop this feature.

Tom : Is there a way to set the time limit to only be active during specified time ranges? For example, from 6am-9pm I’d like the 30min time limit to be active when I visit a blocked site, but after 9pm I’d like the blocking to become inactive and be able to visit the site as long as I want. If I could request a feature, that would be it.

Scott :     a) Could use natural text parser for time of day. (i.e., just enter 8am-5pm) b) If you have a long list of URLs in a blocklist without any word wrap breaking characters, it will make the block set box in the block sets tab really really wide so you have to scroll to see the "Edit" button.

KelAt :
    It’s not a big deal, but my suggestion would be for either of two changes to be made. Maybe I was already clear about this, or maybe I wasn’t:
– Right now, if I have a window with multiple tabs being blocked. Each one, however says “You can click here to access the page once the site is no longer blocked.” but it gives the same link on each page. It would be good if each page could keep the correct link to go back to the page that was blocked.
– It would be even better if the blocked page could just be restored / refreshed automatically after the block period has ended, so that when I return to the browser, I’m not confronted with lots of "blocked" tabs that I have to just close out of or refresh automatically.

Haitrieu :
    How could I sync this extension setting and statistics between home computer and my company computer?
Seth,Volker
    one other thing. how about allowing javascript in the redirect URL – so, for instance, I could send anything that’s blocked to instapaper before it goes and read it later?
Volker
    Right click might be hard for extensions like Chrome Nanny due to Chrome’s extension architecture. I will add an option in the popup page .
     I like the idea of an option to adding to a new url to existing list without raising the challenge . I will implement it in next iteration.
     I’d like to have the blocked URL in the URL line, so the blocked URL can be bookmarked easily or used by other plugins (like read it later or similiar)
     Max Time: add a option so I can only limiting the time between in a time range e.g. “X minutes every X hours between 0900-1200,1300-1700?
     support for Complex rules
Jonathan:
    Combine the idea of adblock plus’s "list" subscription (they keep a running list of known ad sites) with Chrome Nanny.  But your lists could be news, social networking, , etc.  Then one wouldn’t have to block the whole internet, but just, say, "news".

Tim :
    Add an option to track time spent on links clicked from blocked pages.
Angelo :
    I would like to be able to schedule a ‘break time’ each day, during which I can freely browse my blocked sites without accruing any minutes against my time limit. For example, I give myself 30 minutes a day to use up on browsing my blocked websites, but from noon until 1pm, I can browse as much as I want. Maybe, you could implement this as a "Active Time" setting in the general options, which defines during which times the Chrome Nanny extension is active. I could set up my "Active Time" as:  "930-1200,1300-1700" for example.

Jared :
    Great app, but if there was one added feature, I’d be happier.  In Leechblock, whitelisted URL’s can be added to a particular block set, rather than only in an independent group that supersedes all blocked lists anywhere.  Can you see the advantage in doing it that way?  For example, the scenario that works for me at home is the following: one block site blocks the whole internet 24/7 EXCEPT for a select few sites I allow (email, google maps, wikipedia, etc) that I know not to be the major time drainers.  A second block set blocks EVERYTHING starting at 10 pm so I must get off even email and go to sleep (and this block set supersedes the whitelisted url’s in the previous group).

It took me a while to figure this system out (it’s not necessarily intuitive to consider a hierarchical approach), but it is the best, most customizable way to do it for me.  It’d be great if this feature could be added (could even leave the white lists tab as it is, but just add in the ability to white list within each block list)

Completed Features

This will include the list of features that were discussed previously. I will include the version number and date it was deployed.

Features : Set 1

Completed by August 22. Chrome Nanny version 0.964.

Arnaldo : I see what you are trying to do, but could this popup be a configurable option?
kunigas : Let the password requirement for editing as an option (and also the length of it too), I’m fine without pass, but I find it annoying to type it every time I decide to change the blocking rules (and I do it often in experimental periods).
Discussion :
In the general options, add a drop down to decide how the challenge has to be implemented. Possible values include a) No Challenge b) 32 character c) 64 character and d) 128 characters. By default challenge will be 64 characters. If you increase the challenge size, you will be allowed. If you decrease it, then you will be asked for a challenge . For eg , if you try to reduce a 64 character challenge to 32 characters, you will be asked a 64 character challenge.
If a block set is currently being blocked , then trying to edit / delete will trigger a challenge that is specified in general options.

Saravanan : sort blocksets by name atleast when displaying so that the order is consistent
Discussion : This is more of a usability issue rather than a bug.

Features : Set 2

Completed by September 20. Chrome Nanny version 0.98.

Peter,Lukasz,Scott : Would it be possible to have the option to ‘hide’ the list of blocked sites – so that not everybody who goes on my computer could idly click on the nanny icon and be presented with a list of all the sites I’m not visiting.

Discussion : Allow an option to make the information available in the Chrome Nanny icon optional. Should this be extended to control the list in options menu ?

Yavor : jquery’s datepicker – I cannot see the arrows on the top of the picker – they are blue on blue.
Discussion : This is a UI issue and might confuse some users. So, highlight the arrows in the calendar to change the months more clearly.

anonymous : I think the way it lists the times are kinda weird… if I have 5 more minutes on a site it says 00:05 hours.  At first glance it is kinda confusing.
Discussion : If remaining time for a URL is less than an hour display as "x minutes left" . If greater than an hour display as "x:y hours left" .

Sarah : This extension can render the browser unusable (without running from the command line) if a user blocks their homepage with "close tab" selected as the block method. I suggest defaulting to loading about:blank instead to avoid this problem.
Craig Kingston :  The mode of blocking defaults to closing the tab, which is surprising and confusing.  While I am able to redirect it to some specified URL, it would be nice if a third option or at least a default specified URL was a "default -this pages is blocked- web page" (similar to leech block).

Discussion : I will check if it is possible to redirect to about:blank. If not I will redirect to a new page similar to leechblock’s. This will be the default option for new installations. The current settings will not be modified.

Features : Set 3

Completed by Jan 24 2011. Chrome Nanny version 0.984.

Tim, Saravanan : Allow a more expressive block times. For eg instead of block after 60 minutes in a day allow other options like block after 60 minutes in 4 hour/6 hour/ 12 hours etc. I think Leechblock has this feature. Emulate as closely as possible.
Discussion : These two features might need some major changes in the design of Chrome Nanny but looks like very useful features.

Features : Set 4

Completed by Mar 06 2011. Chrome Nanny version 0.988.

Matt : The ability to go into "focus mode", and block a specific set of websites for a specific  amount of time.
Saravanan : Have a feature similar to Leechblock’s lockdown.
Discussion :
The idea of focus mode and lockdown are very similar – The only difference is that focus mode can involve arbitrary sites not in any of the blocksets. There must be some way to enter a set of websites and ask them to be blocked for the next n minutes. In lockdown, all the sites already in Chrome Nanny block sets are blocked for the next n minutes. In both the cases, the user will be specifying the block time.

Features : Set 5

Completed by Jun 19 2011. Chrome Nanny version 0.989.

Fixed a bug in lockdown.

Features : Set 6

Completed by Jul 24 2011. Chrome Nanny version 0.990.

Galen,Toni,EC,Neil,Corey Helfand : .* blocks, among other things, chrome:extension — this is probably bad behavior. Probably shouldn’t block any urls that purport to use chrome as the scheme. Do not block chrome:* and chrome-extension:// pages.
Eric  : Prevent .*.* from being added to the whitelist.

Robust handling of erroneous regexp – When entering regular expressions in black or whitelist, it is validated. Existing incorrect regular expressions are also handled gracefully.

Prevent *.* from being added to Whitelist

Always allow access to Chrome internal pages even if *.* is blocked. This will allow access to , for eg, Chrome extensions page.

Dont strip www/http from url/blocked url. So www.ft.com will not block www.microsoft.com unless the url is ft.com .

If there is any other features you are interested in, please feel free to share in the comments or in the Chrome Nanny’s extension page !

 

Add to DeliciousAdd to DiggAdd to FaceBookAdd to Google BookmarkAdd to RedditAdd to StumbleUponAdd to TechnoratiAdd to Twitter

Read Full Post »

This is a short post to announce that a new version of Chrome Nanny is released. This version incorporates the much requested feature of “Block Sets” .  It also adds a couple of new minor features, new chart types etc.

URLs :

Installation : Chrome Nanny’s extension page.

Updated Instructions : Instructions For Chrome Nanny – A Leech Block like extension for Chrome .

 

Check out the extension and tell me your experience !

Read Full Post »

I wrote a Chrome extension recently called Chrome Nanny  – For more details see Instructions For Chrome Nanny – A Leech Block like extension for Chrome  . This post is primarily about sharing some the tips I learnt during the process of developing the extension.

Application Logs

One of the most important way to debug the extension is using logs. Sprinkle console.log liberally in your code during development. If you want to view these logs, then go to extensions page (Wrench -> Extensions) , select your extension and click on the appropriate page. Most of the time the primary logic will be in your background html page. Hence you need to select this page in the extensions page to get the developer tools. The last tab there is the console tab which will show your logs. Of course, if the console.log is in some other html page (say options page) , then you want to click on appropriate html file in the extensions page. Each active page of the extension starts its own developer tools window and hence the logs dumped in one is not visible in the other.

Usually, this is the behavior you want. But some times, you may want to redirect all the logs to BackGround html’s console. I don’t recommend it although it is pretty convenient. To achieve this write a wrapper function in your BackGround js which takes a string as input and writes it to console. A sample function might look like this.

writeToConsole : function(stuff)
{
    console.log(stuff);
}

In the code for other html files , you can invoke it . In my case , my BackGround js had an object called BackGroundManager. Hence, I invoke the function as

chrome.extension.getBackgroundPage().BackGroundManager.writeToConsole(someText);

Note that to get access to the BackGround, you need to use getBackgroundPage function. I get BackGroundManager object within it and invoke its writeToConsole function. Of course , it can be much simpler in your code. Once you do this , you can watch all the logs in a single place.

If you are lazy to type the whole expression then write another helper function which can return the background page. This might look like

function bg()
{
    return chrome.extension.getBackgroundPage();
}

You can invoke your object using bg().BackGroundManager using chaining.

A Catch in Tab Update

Chrome has a function to make a tab go to a different URL – chrome.tabs.update . This function has two arguments : A tab id and an updateProperties object. updateProperties has a property called URL which accepts a valid URL.

A sample invocation looks like this :

    chrome.tabs.update(tabId,{‘url’:urlToGo});

The behavior of this API is this : If the URL does not have a protocol, then it assumes that you are trying to load some file from your extension folder. This is useful , for example, when you want to show your help file in a tab. A common mistake (which I did) is giving the url  as http://www.test.com . Here the url does not have a protocol and hence it tries to open a file called http://www.test.com in my extension folder. The lesson is that , you should always remember to have a protocol in the URL to show unless you want to show a file from your extension.

What this means is :

Does not work :   

chrome.tabs.update(tabId,{‘url’:’www.mit.edu’});

Works :  

chrome.tabs.update(tabId,{‘url’:’http://www.mit.edu’});

Profiling Extension’s CPU And Memory Usage

When I was developing the extension , I did not want it to hog lot of memory. Chrome is best know for its blazing speed and I would not want to spoil that experience. Chrome has lot of tools to analyze the extension memory.

Method 1 :
Use this method, if you want an overall extension memory consumption and you do not really care to drill down deep. The easiest way is to press Shift+Esc keys. You can also click on the icon near the Wrench icon , select Developer option and select Task Manager. This will show how much memory each tab and extensions are using. This will give you an approximate value of the memory consumed by your extension.

Method 2 :
If you want to dig deep and figure out which parts of the extension contribute to the memory, then you are in luck. Chrome has some great tools. Go to the extensions page and select the background html page. This will open the Developer tools for the extension. You can select the "Profiles" tab. By default this will not contain any information.

Click on the black dot on the status bar and continue using the extension as usual. After some time, click the same icon and stop the profiling. For best results , I would suggest you do some set of actions which exercise most of the functionality of your extension. Now you can see the CPU profile of the extension so far. It will show all the functions which take a long time to run. You can use this information to fine tune your function.

If you are more worried about memory, then the Heap profile can help. Click on the icon which looks like an Eye to start heap profiling. This will give you a break down of all the objects which take up memory. I find this information to be too much for me to process and I usually ignore it.

Disable Selecting Of Text

For Chrome Nanny, I needed a way to prevent user from copying and pasting text. The scenario is this : When user wants to perform some operation that is forbidden, then I ask the user to enter some random 64 character code as a way to discourage them. Now I wanted to prevent them from using copy and paste to circumvent the challenge. I searched a lot and at last found a working solution – The best part was that it was entirely based on CSS and did not use Javascript at all. I got the idea from this stackoverflow page  . The idea is to have a css class like this :

.no-select
{
   -moz-user-select: none;
   -khtml-user-select: none;
   -webkit-user-select: none;
   user-select: none;
}

Now add this class to your textbox. This will prevent them from selecting text !

Callback functions

Lot of things happen asynchronously in Chrome. Almost all of Chrome APIs accept a callback function. Also a typical extension registers event listeners for the events it is interested in . The downside is that many of them can fired simultaneously and if you are not careful, you internal data structures can become inconsistent.

A more common problem is to know that callback functions need not be called immediately. A bad code is this :

chrome.tabs.getSelected(windowId,function(tab){
    tabId = tab.id
});

if(tabId == blah)
    doSomeThing();

This assumes that Chrome will set tabId inside the callback function before coming to the if. The correct way is to bring the logic inside the callback function (or atleast not make the incorrect assumption). A common way to fix it is

chrome.tabs.getSelected(windowId,function(tab)
{
    tabId = tab.id
    if(tabId == blah)
        doSomeThing();
});

I will talk about more stuff in the next part !

 

Add to DeliciousAdd to DiggAdd to FaceBookAdd to Google BookmarkAdd to RedditAdd to StumbleUponAdd to TechnoratiAdd to Twitter

If you liked this post , please subscribe to the RSS feed.

Read Full Post »

I wrote a Chrome extension recently called Chrome Nanny – For more details see Chrome Nanny – A Leech Block like Extension for Chrome  . I learned lot of interesting things in the process and I will try to write some posts on it.

Originally, I thought of writing a tutorial on writing Google Chrome Extensions – but dropped the idea as Google’s tutorial is fairly comprehensive. So instead , I will try to write about stuff which is not in Google’s tutorials. In this post, I will talk about the various Chrome events that are thrown during usage of Chrome. Tracking these events properly is very important for Chrome Nanny which is both a website blocker ( a la Leech Block) and a time tracker. I suspect these transitions are not that important for most extensions. But still knowing these will help you write extensions better.

Chrome has lot of APIs and event handlers. I will focus on some of events and ignore others . More specifically, I will ignore events like attached/detached etc as their event transitions are fairly straightforward. I will focus on tab/window creation,switching and closing events and their interplay. (ie  the events chrome.tabs.onCreated , chrome.tabs.onRemoved , chrome.tabs.onSelectionChanged , chrome.tabs.onUpdated , chrome.windows.onCreated ,    chrome.windows.onFocusChanged, chrome.windows.onRemoved ). You can read about the event handlers and the arguments they take in the resources given in the References section.

Again for sake of convenience, I have assumed that the default URL opened/entered is google.com. The info I have given below is a bit concise but I hope it is quite understandable.

Tab Creation and Updation Events

1. Open a new tab in an exisiting Window
    create tab event {url : chrome://newtab}
    tab selected event for current tab.
    update tab event { url : null, status = loading, tab url = chrome://newtab}
    update tab event { url : null, status = complete, tab url = chrome://newtab}

2. Open a new tab in an existing Window, but Chrome has some extension that redirects to some other URL
    create tab event {url : chrome://newtab}
    tab selected event for current tab.
    update tab event { url : null, status = loading, tab url = chrome://newtab}
    update tab event { url : null, status = complete, tab url = chrome://newtab}
    update tab event { url : google.com, status = loading, tab url = google.com}
    update tab event { url : null, status = complete, tab url = google.com}

3. When you enter an URL in the current tab
The behavior is same if the tab is new or existing.
    update tab event { url : google.com, status = loading, tab url = google.com}
    update tab event { url : null, status = complete, tab url = google.com}

4. Click on a url and make it open in a new tab  – but focus does not shift to new tab
This happens when you right click and say "Open in new tab" or press (ctrl+enter).
    create tab event {url :googe.com}
    update tab event { url : null, status = loading, tab url = google.com}
    update tab event { url : null, status = complete, tab url = google.com}

5. Click on a url and make it open in a new tab – and focus shifts to new tab
This happens when you press (ctrl+shift+enter).
    create tab event {url : googe.com}
    tab selected for current tab.
    update tab event { url : null, status = loading, tab url = google.com}
    update tab event { url : null, status = complete, tab url = google.com}

6. Refresh the Current Tab
Assuming the tab has google.com and you refresh the page.
    update tab event { url : null, status = loading, tab url = google.com}
    update tab event { url : null, status = complete, tab url = google.com}

Window Creation And Updation Events

1. Open a new window
This happens when you press ctrl+n or select "New Window" in Chrome.
    window created event
    Tab creation scenario (1) or (2)
    window focus changed event for current window

2. Open a link in new window
This happens when you right click on a link and say "Open In New Window".
    Window created
    Tab creation scenario (4)
    window focus changed event for current window

3. Open a link in incognito mode or Open a new Incognito window
    No events thrown. (For Chrome version 5.0 and less.  From Chrome 5.0, if you allow access to an extension in incognito mode, then the events are thrown as in the regular scenarios.

Tab And Window Switching Events

For discussion assume we have two windows w1 and w2. w1 has two tabs a1 and b1. w2 has two tabs a2,b2.

1. Shift to different tab in same window
For eg, we are in a1 and we move to b1. This happens when you select the new tab via mouse, or using keyboard like ctrl+tab or select an exact tab using ctrl+tab number.
    for the new tab (a2 here) , tab selected event is thrown

2. Shift to currently focused tab in different window
Assume that tab a1 is selected in w1 and a2 is selected in w2. If you are now in a1 and then select a2 in w2. This one is a bit tricky to execute. It happens when you are able to see both windows (may be because w1 was not maximised) and you selected a2).
    w2 gets a window focus changed event

3. Shift to tab that is not currently focused in different window
Assume that tab a1 is selected in w1 and a2 is selected in w2. If you are now in a1 and then select a2 in w2. This one is also tricky to execute. It happens when you are able to see both windows (may be because w1 was not maximised) and you selected b2.
    w2 gets a window focus changed event
    b2 gets a tab selected event.
4. Switch to another Window
This happens when you do a alt+tab or when you select the window from the bottom panel. Assume w2 is the new window.
    w2 gets a window focus changed event

Tab and Window Closing Events

Assume that we two windows w1 and w2. w1 has tabs a1,b1,c1 . w2 has tabs a2,b2,c2 . Assume current window is w1 and current tab is c1.

1. Close Current Tab
    tab removed event for c1.
    tab selected event for b1.

2. Close Some other tab in same window without going to that tab
Suppose you are in c1 and you close a1 using the close button without going to tab a1. (Else it becomes scenario 1 ) .
    tab removed event for a1

3. Close last tab in window
Assume w1 has only one tab a1. And you close a1.
    Tab removed event for a1.
    Window focus changed event for w2.
    Window removed event for w1.

4. Close Window : Case 1
Assume w1 has a1,b1,c1. The tab with focus is a1.
    Tab removed event for c1.
    Tab removed event for b1.
    Tab removed event for a1.
    Window focus changed event for w2.
    Window removed event for w1.

5. Close Window : Case 2
Assume w1 has a1,b1,c1 in that order. The tab with focus is c1 (last tab).
    Tab removed event for c1.
    Tab selected event for b1.
    Tab removed event for b1.
    Tab selected event for a1.
    Tab removed event for a1.
    Window focus changed event for w2.
    Window removed event for w1.

6. Close Window : Case 3
Assume w1 has a1,b1,c1 in that order. The tab with focus is b1 (second tab).
    Tab removed event for c1.
    Tab removed event for b1.
    Tab selected event for a1.
    Tab removed event for a1.
    Window focus changed event for w2.
    Window removed event for w1.

 

Source Code

If you want to test these event transitions or want a sample extension to play around , you can download a simple extension here.

References

1) Google’s Chrome Extension Getting Started Guide
    Gives a step by step explanation of how to get started and also a comprehensive set of APIs/
2) Chrome API Guide
    Has a fairly comprehensive set of APIs and its documentation.

 

Add to DeliciousAdd to DiggAdd to FaceBookAdd to Google BookmarkAdd to RedditAdd to StumbleUponAdd to TechnoratiAdd to Twitter

If you liked this post , please subscribe to the RSS feed.

Read Full Post »

[Update Nov 15 2011] : Chrome Nanny is now Nanny for Google Chrome. It also has a new home. The link to Google Chrome extension gallery ishttps://chrome.google.com/webstore/detail/cljcgchbnolheggdgaeclffeagnnmhno . Please spread the word !

Leech Block is one of my favorite Firefox extensions. When I made the switch to Google Chrome, the lack of Leech Block like Chrome extension was annoying. In one of my old blog post Two Chrome Extensions I wish Chrome had !! , I had mentioned that the two extensions I miss were Leech Block and one which can track my browsing habits.

I waited for quite some time for some one to make a Chrome extension and then decided to write it myself. Google has a good API documentation and tutorial – so coding was not that hard. In the process, I learned lot of interesting stuff – and my admiration for Chrome has only increased.

What Is Chrome Nanny

Chrome Nanny is a Leech Block like extension for Chrome. It allows you to say don’t allow me to go to a particular site during the time you specify. You can also limit the maximum time that you spend on a site. This means, that you can say you do not want to be allowed to go to facebook.com from 9-5. Even better, you can say don’t allow me to spend more than 1 hour during the time facebook is not blocked (12 AM -9AM, 5 PM – 12 AM). This is probably , the most common way Chrome Nanny will be used. Also you will also not be allowed to edit or delete a blocked URL during the time it is blocked.

If you want to check out the extension, please try it out at Chrome Nanny‘s Google extension gallery. If you want to read the instructions and its features, check out Instructions at Chrome Nanny – A Leech Block like extension for Chrome.

If you try to access a site during the time when it is blocked or after your daily quota is over, you will not be allowed to visit it. By default, Chrome Nanny will close the tab. If you like, you can also redirect the tab to  go to some motivational site. For eg, I make my Chrome Nanny redirect to ocw.mit.edu. Whenever I see that ocean of knowledge, I get a guilty feeling and start to work again 😉

I also added a feature to track the time I spend on some sites I commonly visit – digg, nytimes, hacker news etc. These are the sites, which I do not want to block , but I want to know how much time I spend on them. In Chrome Nanny, these sites are called White Listed Sites. You can add a site and the system will silently start tracking the time you spent on those sites.

Tags are another of my favorite feature. You can create tags to group URLs. For eg facebook and myspace may be in social networks, google reader and technorati in blogs etc. A tag contain multiple URLs and a URL can have multiple tags. Tags are most useful when you chart the time spent on each broad activity (like blogs, news, work etc ).

Chrome Nanny also has a basic charting system. It can provide three charts : Blocked Urls, White Listed Urls and Tags. Each of these can be drawn as a bar or pie chart.

Chrome does not have any easy way to determine if the Chrome tab/window is minimized. This means that it is hard to know that the user is not at the desk. For that, I have an maximum inactive time in General Options. For eg , if it is set to 5 minutes , and there is no activity in Chrome for 5 minutes, then Chrome Nanny stops tracking. In fact , it even gives back the 5 minutes !

If you want to know how much time left in your quota , you can always click on the Chrome Nanny’s icon to see the URLs blocked and allowed now. If an URL is allowed , then it also shows how much time left today too !

Comparison with Stay Focusd and Rescue Time

I noticed that there are two extensions that have functionality similar to Chrome Nanny. One is Stay Focusd and other is Rescue Time. Both are fine extensions. You may want to select the most appropriate extension based on your needs.

Stay Focusd has a single block time for a whole day and all the blocked URLs share this limit. In Chrome Nanny , each blocked URL has individual block time and max limits. In Leech Block parlance, all the Stay Focusd URLs form a single block set while in Chrome Nanny each URL is its own block set.

Chrome Nanny can do the job of Rescue Time partly too ! If you add the urls you want to track in White Listed URLs, then Chrome Nanny will count how much time you spent on each of them. Rescue Time on the other hand tries to track and analyze any url that you visit.

Acknowledgements

I had used jqplot  for charting. It is an excellent charting system and was very flexible. The icon for Chrome Nanny is obtained from the icon set of Smashing Magazine .

Also a special shout out to Suresh, Lokesh, Ashok (who also suggested the name !), Kripa, Divya and Arvi who helped me to test the extension and gave useful suggestions. Thanks a lot guys !

Do check out Chrome Nanny and tell me your opinion !

Add to DeliciousAdd to DiggAdd to FaceBookAdd to Google BookmarkAdd to RedditAdd to StumbleUponAdd to TechnoratiAdd to Twitter

If you liked this post , please subscribe to the RSS feed.

Read Full Post »

[Update Nov 15 2011] : Chrome Nanny is now Nanny for Google Chrome. It also has a new home. The link to Google Chrome extension gallery ishttps://chrome.google.com/webstore/detail/cljcgchbnolheggdgaeclffeagnnmhno . Please spread the word !

Prelude :

I have written a Chrome extension which kinda does some very basic stuff that Leech Block does for Firefox. I also have added some more features (like tags, charts) to Chrome Nanny that makes it more usable IMHO. If you are interested in checking it out, check the Chrome Nanny’s entry in Google Chrome extension gallery.

When I published the extension , the site asked for a web page with instructions for the extension . Even though , I had included instructions in options page of the extension, it makes sense to have  the instructions in a website too . Hence this post !

[Update]

1. The features that are planned to implemented are listed at the page Chrome Nanny Road Map .

2. This post will be updated as and when new versions of Chrome Nanny are released.

I have put the most commonly asked questions in the FAQ.  Please take a look at the FAQ and the comments to see if your issue is addressed. If not please feel free to comment on the post or Chrome Nanny’s extension page.

FAQ

I have added some FAQs based on the comments in the blog post. I will keep them updated as the comments evolve.

1. How do I block a URL (eg : http://www.facebook.com)  for a specific period of time ?

Lets say you want to block facebook between 9AM-5PM. Go to Chrome Nanny’s Options page and select Blocked List tab. Enter facebook.com in the URL. Convert time to be blocked to hhmm format in military time. It becomes 0900-1700. If there are multiple times, then append them with commas. Eg 0900-1200,1300-1700.  Select the days on which facebook has to be blocked. Click “Save URL”.

2. How do I limit accessing facebook to 1 hour a day ?

Suppose you want to access facebook all day but want to limit it to 1 hour at the most in a day. Go to Chrome Nanny’s Options page and select Blocked List tab. Enter facebook.com in the URL.  Enter 0000-0000 in the Blocked Time. Enter 60 in the “Max Time In a Day”. Click “Save URL”.

3. How do I block a url for specific interval but also want to limit the time spent on it in a day ?

This is achieved by a combination of 1 and 2. Lets say you want to block facebook between 9AM-5PM. In the remaining time you want to limit your browsing to 1 hour. To do that, enter facebook.com in the blocked URL , block time as 0900-1700, max time in a day as 60.

4. How do I block all .org sites except wikipedia ?

This can be done using regexp. In the block url , enter .*.org as the url. Enter the appropriate block times and save the blockset. Now go to “White List” tab and enter “wikipedia.org” as white listed url. Chrome Nanny will block all .org sites except wikipedia.

5. Is http, https, www needed ?

No. They are really not needed and Chrome Nanny internally strips them when doing the matching. So facebook.com will block facebook and there is no need to enter the full URL as http://www.facebook.com .

6. Chrome Nanny Crashed my Chrome

Open Chrome Nanny’s options page. In the “General Options” tab,  check the value of “Mode of Blocking”. If it is remove (default) then Chrome Nanny will close the tab if you try to access a blocked URL or if your daily quota is up. If there is a single tab in the window, it might look Chrome has crashed. It has not.

7. Chrome Nanny closed my tab

Chrome Nanny’s default mode of blocking is to remove the offending tab. If you want to redirect to some motivational web page, you can certainly do so. Open Chrome Nanny’s options page. In the “General Options” tab,  select “Redirect” as the value for “Mode of Blocking”. Enter the redirect url. Note that you cannot redirect to a URL that is blocked.

8. Chrome Nanny did not block my page

There are multiple possible reasons for this scenario.

Case 1: Check if the settings are correct. Is Chrome Nanny disabled ? Are you in Incognito mode ? Obvious, but it does not hurt to say again. Should this URL should be blocked now ? You can click on Chrome Nanny’s popup icon to get more details on which URLs are blocked now.

Case 2 : Is the blocked URL a substring of the tab’s current URL ? For eg having facebook.com will block http://www.facebook.com/home.php , http://www.facebook.com/settings.php and so on. For some websites, the URL with which we access may not be the final URL.  Eg reader.google.com may not work. Enter blocked url as google.com/reader. Enter mail.google.com instead of gmail.com and login.live.com instead of hotmail.com and so on.

Case 3 : Check if blocked list and white list URLs clash.

White listed URLs take precedence and if a URL matches white list and block list then it is allowed. A sample scenario is to block Google reader but allow all other google pages. To do this entering google.com/reader in blocked list is enough. If you add google.com in white list , then Google Reader is also allowed as it matches the white listed URL “google.com” .

Case 4 : Check if any of your blocked or white listed URLs using regular expressions (eg using “*” in the URL). If so, validate it in “Validate Regular Expressions” tab. Note that an error in any of the regexp URLs can cause Chrome Nanny to not block other URLs.

Case 5 : Click on Chrome Nanny’s popup icon (the one that looks like a clock). Check if the URL is blocked now. If it is , then Chrome Nanny will block the URL sooner or later. Chrome Nanny uses callback functions of Chrome’s events to perform the blocking. If they are not called , Chrome Nanny might not block the tab immediately .

Don’t worry : Chrome Nanny has other checks too ! It checks all the tabs every minute and blocks tabs if necessary. Also if you switch to another tab or refresh the tab , the tab is checked again. So if Chrome Nanny does not block it immediately then give it some time. If the tab is not blocked even after one minute (Although, Chrome Nanny’s popup says otherwise) then please check the troubleshooting section to see how to contact the developer about the error.

9. Chrome Nanny blocked my page before the deadline is up !
Chrome Nanny has a feature which allows you to specify total time you can spend on all blocked URLs in a day. Suppose you set it to 60 minutes. Then if the total time you have spent on all blocked URLs exceed 60 minutes, then all blocked URLs will be blocked immediately, even though individual URLs may have some more time left. ie This feature overrides the individual URL settings. To disable this feature , set Maximum Allowed minutes in a day for Blocked URLs to 0 in General Options tab.

10. Can I block a subdomain or a specific url ?

Sure. For eg, if you want to block Google Reader alone (but not other google pages) enter google.com/reader in the blocked list. This will allow all Google pages but will block Google Reader.

11. Can I block certain patterns of URLs ?
A sample scenario is this : I want to block all Google searches for games but other queries are ok. Yes, you can do it by having a blocked URL as “google.com/search.*games” .

12. Some examples for regular expressions

Please note that you need to use “.*” whenever you want to use “*” in the regular expression. (Eg .*.wordpress.com instead of *.wordpress.com )

a) google.*
Matches google.com , google.co.in, google.com/reader , picasaweb.google.com
Does not match any URL that does not have the word google in it.

b) http://www.google.*/reader
Note : Chrome Nanny internally strips http,https and www. So this regexp is equivalent to google.*/reader
Matches http://www.google.com/reader/view
Does not match google.com, google.co.in, picasaweb.google.com, reader.google.com

c) *.wordpress.com
Does not match anything. Worse yet, it can prevent validtion of other blocked URLs. If you verify this URL , you get an error “Invalid regular expression: /*.wordpress.com/: Nothing to repeat”. This is because , the “*” operation needs some character to repeat and when you dont give any, it errors out.

d) .*.wordpress.com
Correct way to block all wordpress.com blogs. Here the “.*” matches any characters that come before the domain and hence it will block all of them. If you want to allow say, “saravananthirumuruganathan.wordpress.com” but block other wordpress blogs, then create a “.*wordpress.com” blocked URL and make “saravananthirumuruganathan.wordpress.com” as a whitelisted URL.

e) test

This will match any URL that contains the word test. For eg test.com, blahtest.com, foo.com/test , bar.com/g.php?val=test etc.

13. I do not want the Challenge that occurs when I try to edit/delete a blockset when it is blocked !
The 64 character (default) challenge that Chrome Nanny raises when you try to edit/delete a blockset when it is currently blocked is one of the few hurdles in your way before you start whiling away your time ! I do understand there are many “legal” scenarios like experimenting with Chrome Nanny when challenge is an annoyance. So use the following feature only when needed. Go to General Options and then Length Of Challenge Text . Reduce the length 0. To prevent abuse, Chrome Nanny will ask for challenge once. If the length is changed to 0, then further changes do result in a challenge. Once you are done with the playing around, please do increase the challenge text length.

14. I do not want the blocked URLs to be displayed in the popup !
By default, Chrome Nanny will show the URLs currently blocked, how much time left in other blocked URLs and other details. If you do not want it to be displayed in the icon popup, go to Options , click ‘General Options’ tab, and select ‘No’ for the field ‘Show blocked URLs in popup ?’ . After this, when you click on the Chrome Nanny icon, it will display a bland message instead of the blocked URL details.

15. I think I have found a new bug ! Or How do I troubleshoot Chrome Nanny ?

I have tested Chrome Nanny extensively but bugs do creep up. Please check if you can reproduce the error consistently. If so, please point out the bug and the steps to reproduce in any of the following ways : comment at Chrome Nanny’s extension page OR comment in Chrome Nanny’s instructions blog post OR email the developer at saravanan DOT thirumuruganathan AT gmail DOT com .

It would be great if you can email the settings of Chrome Nanny also. Easiest way is to email the file chrome-extension_gpdgmmdbbbchchonpfanphofpplhmcmn_0.localstorage at ~/.config/google-chrome/Default/Local Storage (If using Linux and Chrome) or ~/.config/google-chrome/Default/Local Storage (using Linux and Chromium) or at C:\Users\\AppData\Local\Google\Chrome\User Data\Default\Local Storage (In Windows) .

Optionally you can also give me the logs when the bug occurs. To get Chrome Nanny’s logs , click on the Wrench icon – Select Extensions. Go to Chrome Nanny and click on “background.html” . This will open Chrome’s developer tools. Now try reproducing the bug and copy the log it generates. This will be very helpful for additional debugging.

16. I have a patch for feature X . How do I send it to you ?

It is wonderful that you took time to write a patch. Please send an email to saravananDOTthirumuruganathanATgmailDOTcom with the patch details and the file. I will test it and apply it to the extension. The latest code of Chrome Nanny will can be downloaded from the repository here . If you need additional help on the code please take a look at my post “How to Read the Source Code of Chrome and Firefox Extensions” .

Instructions

First of all, Thanks for using Chrome Nanny !

Chrome Nanny is a Chrome extension which can keep your browsing habits in check. Do you spend more time on facebook than on work ? Do you spend time more time in Google Reader or Digg and later wish you had not spent as much time ? Do you want to know how much you spent on Flick ? If so , Chrome Nanny is for you. Using Chrome Nanny, you can limit yourself from going to some sites on pre determined times or limit the time you spend on some sites. If you do not want to block a site, but want to know how much time you spend there, Chrome Nanny can do that for you too ! If you have used Leech Block for Firefox , you can recognize that Chrome Nanny does something similar but with a twist.

Note : If you are in Google Chrome version 5 or more , then enable this extension to run in Incognito mode too! Chrome Nanny will not like it if you visit blocked sites in Incognito mode. Will she ?

General Options

Mode Of Blocking decides what to do if you are visiting a website during blocked hours or after exhausting all the time you allocated yourself for the site. The default option is to remove the tab which may not be ideal for you. If you want the tab to be redirected to some motivational sites then you can select the redirect option and give a redirect url. You can specify a web page or a local html page (using file:// prefix) . Note that if you have only one tab, mode of block is”remove” and the url is blocked now, the entire window will be closed.

Stop Timer after Chrome is inactive for x minutes – Chrome does not notify when you minimize a Window/Tab. Chrome Nanny does not want you to lose the minutes you were not at the desk. You can enter some number in this field. For eg, if you are not active for 5 minutes, then Chrome Nanny will stop tracking the minutes till you come back.

Maximum Allowed minutes in a day for Blocked URLs – Use this field if you want to set a single limit to the time you spend on Blocked URLs. This value will override the individual Blocked URL limits. As an example , lets say you added facebook.com to Blocked URL list and set Max Time In a day as 60 minutes. If you now set, Maximum Allowed minutes in a day for Blocked URLs as 30 minutes, then facebook.com will not be accessible after 30 minutes . The same holds when you have multiple Blocked URLs. If the sum of time spent on all the URLs exceed this field, then all Blocked URLs will be blocked.

Length Of Challenge Text  – This determines the length of the Challenge text that Chrome Nanny will ask if you  try to edit/delete a blockset when it is  currently blocked. Reducing this field will also decrease the length of the challenge text. This field was added because in “some” scenarios (eg when playing with Chrome Nanny) , Challenges are an annoyance. Please use this field with discretion. To make changing this field a little hard to use, when you reduce the length of the Challenge, Chrome Nanny will perform a Challenge. So if you try to reduce a 64 character challenge  to 32 character, you will be challenged with a 64 character random string before being allowed to change it. Making the length as 0, removes all challenges.

Tags

Tags are a way to aggregate individual URL statistics. For eg you may spend lot of time on nytimes.com and Google news. If you want to aggregate the results into a “news” tag, then you can use the Tags tab for it. An url can belong to multiple tags.

Blocked URLs

Do you think, you spend too much time on Facebook ? This is the tab where you can use to limit your visits.

Block Set Name : Chrome Nanny allows you to group multiple URLs into a block set. Enter a name that you think summarizes the list of URLs. Eg News, Social Networks, Blogs etc.

URLs : Add the websites in this block set here. You need not add a full site url. So facebook.com will be enough. No need to add the whole “http://www.facebook.com”. Note that the url must be the “final” URL of the page that you want to be blocked. This means that gmail.com is better written as mail.google.com , reader.google.com is better written as google.com/reader and so on. You can add as many URLs you want in the text area. Separate them by newline (Enter key). ie a.com enter b.com blocks both a.com and b.com.

Add Tag : If you add any tags in the Tags tab, then you will see those tags here. You can add any number of tags for the url here. Just select the tag and keep clicking “Add Tag”. A URL can have multiple tags.

Block Time : This is the most important information. This decides when the url should be blocked. So if you want it to be blocked from 9 AM to 5 PM, then you encode it as 0900-1700. This is nothing but expressing start and end time as hhmm-hhmm in the 24 hour format. You can add multiple time blocks by separating them by comma. So to block between 9AM-5PM and 7PM-9PM, you write 0900-1700,1900-2100. Note that during the time a URL is blocked, you will not be able to edit or delete the URL.

Max Time : This an optional field. If you want to limit the time you spend on a site during your allowed time, then this field is useful. For eg, taking the example above, if you want to block between 9AM-5PM but you want to limit your browsing to 1 hour in the allowed time (12 AM-8:59 AM , 5:01 PM-11:59 PM) then you enter 0900-1700 in Block Time and 60 in the Max Time In A Day.
Apply On Days : Chrome Nanny understands that you may want to relax on weekends. So if you want your strict rules to apply only on weekdays, uncheck the weekends here.

This field also allows you to specify the block time in a granular level. For eg, you can set yourself to be allowed to browse the site for a maximum of 10 minutes each hour. To do that, set max time as 10 and in the drop down select for every “1 hour’”.

Note that you can edit or delete all the URLs any time when it is not blocked.

Lock Down

Lock down tab allows you to go into a focus mode by blocking some web pages for next “n” minutes. To do that, select the list of blocksets and then set the time to lock down. Note that once a lock down is active, you cannot edit or delete the blockset. Additionally, there is no way to cancel a lockdown too.

The lockdown information is visible in popup and also in the ‘Lockdown Information’ block.

White Listed URLs

If you do not want to block a URL but want to find how much time you spend each day, then use the White Listed URLs tab. Any URL added here is not blocked, but will be tracked and can be charted.
URL : Enter the URL of the site you want to be tracked. Again, you can enter just the domain name to track any page in the site.
Add Tag : As with Blocked URLs , you can add tags to White Listed URLs too !

Statistics

If you want to visualize how you spent your days with respect to the URLs you entered in Chrome Nanny, then this is the tab for you. You can enter the date range and Chrome Nanny will give you four charts. One each for Blocked URLs, Block Sets, White Listed URLs and tags. You can select between Bar Chart and Pie Chart !.

Validate Regular Expression

If you are going to use a regular expression in the URL, then you can use this tab to validate it. A bad regexp can cause syntax error in the code and *might* cause Chrome Nanny not to block other URLs.

Validating a Regular Expression : Enter your regexp in “Regular Expression for URL” and click “Test Regular Expression”. Check the field “RegExp Error”. If there is any error in regexp, it will be displayed here.
Verify if an URL is blocked : Enter the regexp in “Regular Expression for URL” . Enter URL to be tested in “Test URL”. Click “Test Regular Expression”. Check the fields “RegExp Error” and “Match”.

Add to DeliciousAdd to DiggAdd to FaceBookAdd to Google BookmarkAdd to RedditAdd to StumbleUponAdd to TechnoratiAdd to Twitter

If you liked this post , please subscribe to the RSS feed.

Read Full Post »

Older Posts »