How to build a chrome extension

Chrome extensions allow you to add a new functionality to Chrome without having any knowledge about the actual browser source code. New extensions can be implemented using HTML, CSS and JavaScript. In the following example, we implement a word counter extension which helps to count characters, words, syllables and sentences of a selected text in the page. It also calculates the Flesch readability score of the text. The Flesch readability score distinguishes the level of understanding of a text for audiences. If the score is less than 30, the text is distinguished difficult. If the score is greater than 90, the text is distinguished easy and if it is between 30 and 90 it is moderate.

1. Building a new extension

First, create a directory to implement the extension. Then, create a manifest file named manifest.json. This manifest is nothing more than a metadata file in JSON format that contains properties like extension’s name, description, version number and so on. At a high level, it will be used to declare to Chrome what the extension is going to do, and what permissions it requires in order to do those things.

In this example’s manifest, we declare a browser action, the activeTab permission to see the URL of the current tab, and the host permission to access the external Google Image search API.

{
  "manifest_version": 2,
  "name": "Word counter",
  "short_name":"Word count",
  "description": "This extension helps to count words and sentences of a selected text in the page.",
  "version": "4.0",
  "icons":
  {
  	"128":"icon.png",
  	"16":"icon.png",
  	"48":"icon.png"
  },
  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html",
    "default_title": "Word counter"
  },
  "permissions": [
    "activeTab",
    "https://ajax.googleapis.com/"
  ]
}

In the browser_action, two resources are defined icon.png and popup.html. Both files must exist in the same directory that you created.

screen-shot-2016-12-19-at-9-53-57-pm

  • icon.png will be displayed next to the Omnibox, waiting for user interaction. It is a 19px-square PNG file.
  • popup.html will be rendered inside the popup window and will be displayed in response to a user’s click on the browser action. It’s a standard HTML file.
<!doctype html>
<html>
  <head>
    <title>Word Counter Extension's Popup</title>
    <style>
      body {
        font-family: "Segoe UI", "Lucida Grande", Tahoma, sans-serif;
        font-size: 100%;
      }
      #text {
        white-space: pre;
        text-overflow: clip;
        overflow: hidden;
        font-family: Tahoma, sans-serif;
        font-size: 12px;
        max-width: 400px;
      }
    </style>
    http://popup.js
  </head>
  <body>
    
</body> </html>
  • The actual logic of rendering the content of the popup is implemented in popup.js.
/**
 * Get the current URL.
 *
 * @param {function(string)} callback - called when the URL of the current tab
 *   is found.
 */
function getCurrentTabUrl(callback) {
  var queryInfo = {
    active: true,
    currentWindow: true
  };

  chrome.tabs.query(queryInfo, function(tabs) {
    var tab = tabs[0];
    var url = tab.url;

    console.assert(typeof url == 'string', 'tab.url should be a string');
    callback(url);
  });
}

function getNumberOfSyllables(text){
  var n = 0;
  var arr = text.split(" ");
  for (var i = arr.length - 1; i >= 0; i--) {
    var word = arr[i];
    word = word.toLowerCase();                                     
    if(word.length <= 3) { n += 1; continue; }                     
    word = word.replace(/(?:[^laeiouy]es|ed|[^laeiouy]e)$/, '');   
    word = word.replace(/^y/, '');                                 
    n += word.match(/[aeiouy]{1,2}/g).length;  
  }
  return n;
}

function renderText(text) {
  var w = text.split(/[^\s]+/).length - 1;
  var st = text.split(/[^.!?]+/).length - 1;
  var c = text.length - 1;
  var cw = text.replace(/\s+/g, '').length;
  var sy = getNumberOfSyllables(text);
  var fr = 206.835 - 1.015 * (w/st) - 84.6 * (sy/w);
  var readability;
  if(fr <= 30) {     readability = "Difficult";   } else if(fr >= 90){
    readability = "Easy";
  } else{
    readability = "Moderate";
  }

  var finalText = "Number of characters with space: " + c + "\n" + 
                    "Number of characters without space: " + cw + "\n" + 
                    "Number of words: " + w + "\n" + 
                    "Number of syllables: " + sy + "\n" +
                    "Number of sentences: " + st + "\n" +
                    "Flesch readability score: " + readability + " ";

  document.getElementById('text').textContent = finalText;
}

document.addEventListener('DOMContentLoaded', function() {
  getCurrentTabUrl(function(url) {

    chrome.tabs.executeScript( {
      code: "window.getSelection().toString();"
    }, function(selection) {
      if(!selection || selection == ''){
        document.getElementById('text').textContent = "Please select your text!";
      }else
        renderText(selection[0]);
    });

  });
});

Note: To add a tooltip for the extension, set the default_title key in the manifest file in the browser_action.

You should now have four files in your working directory: icon.png, manifest.json, popup.html,popup.js. Now let’s load the new extension files into Chrome.

To load the extension on the browser, follow these steps:

  1. Visit chrome://extensions on browser or open up the Chrome menu by clicking the icon to the far right of the Omnibox: The menu's icon is three horizontal bars. and select Extensions under the Tools menu to get to the same place.
  2. Ensure that the Developer mode checkbox in the top right-hand corner is checked.
  3. Click Load unpacked extension… to pop up a file-selection dialog.
  4. Navigate to the directory in which your extension files live, and select it.

If the extension is valid, it’ll be loaded up and active right away! If it’s invalid, an error message will be displayed at the top of the page. Then, correct the error, and try again.

Note: The manifest file is parsed only once the extension is loaded. If you want to see the new changes in action, the extension has to be reloaded. Visit the extensions page (go to chrome://extensions, or Tools > Extensions under the Chrome menu), and click Reload under the extension. All extensions are also reloaded when the extensions page is reloaded, e.g. after hitting F5 or Ctrl-R.

3. Source code

You can download the source code here. Also, the published version of the chrome extension can be found here: https://chrome.google.com/webstore/detail/word-counter/cgfjdjopdhopjgbcinafnfpcpjfeaidm

Advertisements

Is good enough really good enough?

I had a pleasure to present this article as a speech at GirlGeekDinner event in Sydney on Dec 2016. This article is related to my experience at work and life which comes with some research that I’ve done about this topic.

czik7rtukaazeht

In this article, I’m going to discuss, about being perfectionist and how being perfectionist can make us successful or unsuccessful.

We all might be somehow perfectionist in different aspects of our life for example at work or in our relationships. Almost everyone knows someone who is perfectionist if they are not perfectionist themselves.

 

What’s the pros of being a perfectionist?

  • High standards

Perfectionists have very high standards for everything, and always they are very specific on deciding what to wear, who to be friend with, the quality of delivery of a work and etc. They can easily meet the expectations of clients, managers or others because of their high standards.

  • Good organisers

Perfectionists like to declutter everything, because of that they might have a very clean desk. They might be also really good in checking emails and making sure, they don’t have any unread emails and declutter their inbox every hour.

They also set everything in order. They set up everything really well such as meetings and things that need to be done by providing a checklist for them which makes them a good organiser.

  • Attention to details

Perfectionists are really good on spotting mistakes while others don’t see them. This makes them to be very details oriented. For example, they like to double check their work many times to make sure that the output is as perfect as possible in every aspect.

o-perfectionist-facebook-696x3482x

  • Great analysers

Because they pay attention to every single detail, they have very good analytical skills. They can think of details that others may not even have noticed before and try to include it in the output. Which it makes their work really great as an employee and create a positive impression at work for them.

  • Polished results

Their work is mostly crystal clear because they think of everything and worked on every detail. Sometimes, their colleague might wonder how they managed to get everything like that and how much time they spend and how they are patient to produce such a work with great accuracy.

 

With all these, being perfectionist looks awesome, their work, their life looks great and everyone think they have everything under control. But is that all? Are they always perfect?

 

What are the cons of being a perfectionist?

  • All or nothing

Perfectionists believe everything should be done really well or shouldn’t do it at all.

To give you an example, I had a research subject at Uni and the subject was really difficult and required lots of interviews and research. We were two girls and 13 gentlemen in the class. In the last session, we had to present our assignment to our lecturer and classmates. My female classmate didn’t attend the session and gave up on all her efforts and didn’t pass the subject. I asked her later why she didn’t attend the session while she got the exact same mark as me for the first assignment. She told me “I wasn’t happy about my first assignment as it wasn’t perfect. So, I didn’t want to continue with that for the second assignment. I will do the subject another time”.

Believe me, she wasn’t bad in the subject at least in comparison with other guys who attended, even a few of them had a very low-quality assignment. I’m sure if she wasn’t perfectionist about the delivery of her assignment she would have got a good mark on that subject.

When you think only about the end result then you don’t leave any room for mistakes and it makes everything difficult and stressful. You also might fear of any possible failure, because you don’t like to be imperfect.

  • What if?

Whenever something goes wrong or they cannot achieve their goal, they keep wondering “What if?” What if I did this or didn’t do that. Thinking about the outcomes hundred times and feel that everything is their fault because they didn’t achieve it. This makes them depress and they can even lose their confidence. They’re always quick to beat themselves up and feel extremely bad about a mistake for a long while. And sometimes they might want to feel better, so they look for to get others acceptance which is not the best way to feel perfect. Because gradually their confidence will be depended on others acceptance.

  • Success is never enough

Whatever they do, they always aim for higher than that. For example, if they want to achieve a goal and they get that, instead of celebrating the success and being happy about what they achieved, they just thinking about pushing a bit more to get the next success. But this could result in losing confidence because they never feel happy about what they achieve and get, instead, they expect more.

  • Procrastination

Because they always like to be perfect, they constantly waiting for the right moment to work on their goals. They only want to start when they are ready, so, they postpone the work. For example, if you want to have your own start-up, just do it. Don’t sit somewhere and say I will do it once I get less busy and be in a better situation and etc. That time is never going to happen.

  • Slow

Perfectionists like to get everything done according to their expectations and standards. They can be slow in delivering the outcome in comparison with others. Because they spend lots of time to make every piece of work to perfection.

175032-849x565-perfectionist

Generally, being perfectionist is very common among girls because we learn to be perfect since childhood, we are taught to paly safe and don’t take risks. On the other hand, boys are taught to be brave, swing over the tree and take the risk at any time of their life.

So, when they become an adult and if they want to apply for a job, mostly girl if they don’t feel they match 100% with the job, they don’t apply while men will apply even if they match only 60%.

How to overcome perfectionism

Sometimes the perfection becomes an obsession. If you think you have any of these characteristics and like to overcome that, here what you can do.

  • Remove the all-or-nothing mindset

In the real world, no one achieves success smoothly without failure. No entrepreneur succeeds without having failed in the past. In reality, everything happens in progression, not in all-or-nothing manner.

  • Learn to respect and love yourself

You might do self-neglect a lot especially when things go wrong. But you should know that we should love ourselves and flaws, e.g. instead of working hard and having not enough sleep to make something to perfection or, instead of just keep telling ourselves that it was our fault when something went wrong, keep our health the highest priority and give sometimes to be relaxed.

  • Celebrate every progress, victory and failure

Allocate time for yourself and those you love. Leave the work behind and don’t prioritise work over your life and celebrate both your victory and failures.

When you don’t achieve a particular goal, you feel you failed. But I’m sure you have definitely learnt new things. You shouldn’t be hard on yourself because it will result in the lack of confidence and stop taking the risk in the future. Don’t lose your confidence with fear of failure.

  • Delegate and let go

Sometimes, it is a bit tough to work with perfectionists because they think they can do everything better than anyone else. But my suggestion is that trust your teammates and give them the work and let it go. For example, in programming, if you want to deliver a perfect project, it requires lots of work and time and resources; we all know that a project is the result of everyone in the team and not only one person.

  • Good enough mindset

I know perfectionists like to have high standards and think of any details, but sometimes good enough really is good enough and they can stop there instead of wasting time on perfecting details that are not that important.

xperfectionist_1-jpg-pagespeed-ic-nehzn19ydr

Now, what do you think about yourself? Are you a perfectionist? Do you want to be in some aspects and don’t want to be in other aspects of your life or work? I’ll leave that to you but keep this in mind that being brave and taking a risk can make your life more interesting than being perfect in everything, that’s my experiences. I used to be perfectionist in many aspects of my life and work but now, I’m not and I feel happier than before and my life looks much perfect than before.

 

How to implement Thread pool in Java

A thread is an independent program’s path of execution. In java, each thread extends the java.lang.Thread class or implements java.lang.Runnable.

Multithreading refers to the execution of two or more threads concurrently within a single task.In multithreading, each task can have many threads, and these threads can run concurrently, either asynchronously or synchronously. You can find more information about thread and multithreading in another tutorial that I wrote about multithreading here.

1. What is Thread pool

Thread pool represents a group of worker threads which execute tasks, each thread can be reused many times. If a new task is submitted when all threads are active, they will wait in the queue until a thread is available. Thread pool implementation internally uses LinkedBlockingQueue for adding and removing tasks to the queue.
What we usually want is a work queue combined with a fixed group of worker threads, which uses wait()and notify() to signal waiting threads that new work has arrived. The following example shows a simple work queue which is queue of Runnable objects. This is a common convention for schedulers and work queues, although there is no particular need imposed by the Thread API to use the Runnable interface.
package tutorials;

import java.util.concurrent.LinkedBlockingQueue;

public class ThreadPool {
    private final int nThreads;
    private final PoolWorker[] threads;
    private final LinkedBlockingQueue queue;

    public ThreadPool(int nThreads) {
        this.nThreads = nThreads;
        queue = new LinkedBlockingQueue();
        threads = new PoolWorker[nThreads];

        for (int i = 0; i < nThreads; i++) {
            threads[i] = new PoolWorker();
            threads[i].start();
        }
    }

    public void execute(Runnable task) {
        synchronized (queue) {
            queue.add(task);
            queue.notify();
        }
    }

    private class PoolWorker extends Thread {
        public void run() {
            Runnable task;

            while (true) {
                synchronized (queue) {
                    while (queue.isEmpty()) {
                        try {
                            queue.wait();
                        } catch (InterruptedException e) {
                            System.out.println("An error occurred while queue is waiting: " + e.getMessage());
                        }
                    }
                    task = queue.poll();
                }

                // If we don't catch RuntimeException,
                // the pool could leak threads
                try {
                    task.run();
                } catch (RuntimeException e) {
                    System.out.println("Thread pool is interrupted due to an issue: " + e.getMessage());
                }
            }
        }
    }
}

It is important to use synchronise block while working with the queue, to control the access of threads to the queue.

package tutorials;

public class Task implements Runnable {

    private int num;

    public Task(int n) {
        num = n;
    }

    public void run() {
        System.out.println("Task " + num + " is running.");
    }
}
import tutorials.Task;
import tutorials.ThreadPool;

public class Main {

    public static void main(String[] args) {
        ThreadPool pool = new ThreadPool(7);

        for (int i = 0; i < 5; i++) {
            Task task = new Task(i);
            pool.execute(task);
        }
}

In the above example, we used notify() instead of notifyAll(). Because notify() has more desirable performance characteristics than notifyAll(); in particular, notify() causes many fewer context switches, which is important in a server application. But it is important to make sure when using notify() in other situation as there are subtle risks associated with using notify(), and it is only appropriate to use it under certain specific conditions.

The following figure demonstrates the thread pool design in the above example.

screen-shot-2016-12-11-at-10-17-55-pm-copy
Figure1. Thread pool design

2. Effective use of thread pools

Thread pool is a powerful mechanism for structuring multithreaded applications, but it is not without risk. Applications built with thread pools could have all the same concurrency risks as any other multithreaded applications, such as deadlock, resource thrashing, synchronization or concurrency errors, thread leakage and request overload.

Here are some points:

  • Do not queue tasks which wait synchronously for other tasks as this can cause a deadlock.
  • If the task requires to wait for a resource such as I/O, specify a maximum wait time and then fail or requeue the task execution. This guarantees that some progress will be made by freeing the thread for another task that might complete successfully.
  • Tune the thread pool size effectively, and understand that having too few threads or too many threads both can cause problems. The optimum size of a thread pool depends on the number of available processors and the nature of the tasks on the work queue.

3. Conclusion

The thread pool is useful for organizing server applications and it is really important to implement it properly to prevent any issues such as deadlock and complexity of usage for wait() or notify(). So, it is recommended to consider using one of the Executor classes from util.concurrent, such as ThreadPoolExecutor, rather than writing thread pool from scratch. If the requirement is to create threads to handle short-lived tasks, you could consider using a thread pool instead.

4. Download the Source Code

This was a tutorial for thread pool, to download the source code, click here.