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.

Binary search

Binary search or half-interval search is a fast search algorithm to find the position of a target value in a sorted array. The run-time complexity of this algorithm is Ο(log n).

Binary search
Binary search

In binary search, the target value is compared to the middle element of the array; if they are not equal, the half of array which target can not lie, is eliminated and the search continues in the remaining half until it is successful.

1. Algorithm

  1. Set L to 0 and R to n − 1.
  2. If L > R, the search terminates as unsuccessful.
  3. Set m (the position of the middle element) to the floor of (L + R) / 2.
  4. If A[m] < T(target value), set L to (m + 1) and go to step 2. If A[m] > T, set R to (m – 1) and go to step 2.
  5. Now Am = T, the search is done; return m.

2. Java code

/**
 * Array should be sorted asc
 * The implementation is not recursive
 * Complexity of the algorithm
 * Best: O(1)
 * Worst: O(logn)
 */
 public static int binarySearch(int[] array, int val){
     int low = 0;
     int high = array.length - 1;
     while(low < high){
         int mid = (high + low) / 2;
         if(array[mid] == val)
             return mid;
         else if(array[mid] < val)
             low = mid +1;
         else
             high = mid - 1;
     }
     return -1;
 }

2.1. Recursive implementation

/**
 * Array should be sorted asc
 * The implementation is recursive
 * Complexity of the algorithm
 * Best: O(1)
 * Worst: O(log n)
 */
 public static int binarySearch(int[] array, int val, int low, int high){
     int mid = (high + low) / 2;
     if(high < low)
         return -1;
     if(array[mid] == val)
         return mid;
     else if(array[mid] < val)
         return binarySearch(array, val,mid + 1, high);
     else
         return binarySearch(array,val,low ,mid - 1);
 }

Linear search

Linear search or sequential search is a simple search algorithm for finding a target within a list. In this type of search, a sequential search checks every element within the list for a target value till a match is found. Otherwise, the search continues until the end of the list.

In the best case, the complexity of this algorithm is O(1) in the worst case, is O(n).

1. Algorithm

Linear Search ( Array A, Value x)

Step 1: Set i to 1
Step 2: if i > n then go to step 7
Step 3: if A[i] = x then go to step 6
Step 4: Set i to i + 1
Step 5: Go to Step 2
Step 6: Return Element x Found at index i and go to step 8
Step 7: Return -1
Step 8: Exit

2. Java Code

/**
* Simple Linear Search
* Complexity of the algorithm
* Best: O(1)
* Worst: O(n)
*/
public static int linearSearch(int[] array, int val){

    for (int i = 0; i < array.length; i++) {
        int num = array[i];
        if(val == num){
            return i;
        }
     }
     return -1;
}

Microservices vs. SOA

These days, there are a lot of discussions about Microservices at the workplace or in tech talks. And if you have worked with SOA before, you might wonder what is the difference between SOA and Microservices. Here is a comparison of both architectures in details.

1. SOA

Service Oriented Architecture is a software architecture pattern, which application components provide services to other components via a communications protocol over a network. The communication can involve either simple data passing or it could involve two or more services coordinating connecting services to each other. Services (such as RESTful Web services) carry out some small functions, such as validating an order, activating account, or providing shopping cart services.

There are 2 main roles in SOA, a service-provider and a service-consumer. A software agent may play both roles. The Consumer Layer is the point where consumers (human users, other services or third parties) interact with the SOA and Provider Layer consists of all the services defined within the SOA. The following figure shows a quick view of an SOA architecture.

screen-shot-2016-05-29-at-11-33-12-am
Figure 1: SOA architecture

Enterprise Service Bus (ESB) is a style of the integration architecture that allows communication via a common communication bus that consists of a variety of point-to-point connections between providers and consumers. In addition to above, the data storage is shared within all services in SOA.

Now, let’s take a look at Microservices architecture, then compare both together.

2. Microservices Architecture

Microservices is a software architecture pattern in which complex applications are composed of small, independent processes communicating with each other using language-agnostic APIs.

Microservices must be a real need in the system architecture as it could be designed wrongly. It means a service should be independently deployable, or be able to shut-down a service when is not required in the system and that should not have any impact on other services. The following figure shows a quick view of a Microservices architecture.

screen-shot-2016-05-29-at-11-33-39-am
Figure 2: Microservice architecture

As shown above, each service has its own database or a database is shared between a few of microservices.

3. Microservices Architecture vs. SOA

As discussed above, both architectures have similar pros and cons and some differences. In both architectures, each service – unlike a monolithic architecture – has a certain responsibility. Thus, services can be developed in various technology stacks which bring technology diversity into the development team. The development of services can be organized within multiple teams, however, each team needs to know about the common communication mechanism in SOA.

In microservices, services can operate and be deployed independently of other services, unlike SOA. So, it is easier to deploy new versions of services frequently or scale a service independently.

In SOA, ESB could become a single point of failure which impacts the entire application. Since every service is communicating through ESB, if one of the services slow down, could cause the ESB to be clogged up with requests for that service. On the other hand, microservices are much better in fault tolerance. For example, if there is a memory leak in one microservice then only that microservice will be affected. The other microservices will continue to handle requests.

In both architectures, developers must deal with the complexity of architecture and a distributed system. Developers must implement the inter-service communication mechanism between microservices (if the message queue is used in Microservice architectures) or within ESB and services.

Unit Testing is more difficult as developers must mock the communication mechanism in tests. Due to many different service types, deployment and operational complexity are a concern in both architectures.

In SOA, services share the data storage (as shown in Figure 1) while each service can have an independent data storage in microservices. Sharing data storage has its pros and cons. for example, the data can be re-used by between all services while it brings dependency and tightly coupling within services.

Last but not least, the main difference between SOA and microservices lies in the size and scope. Microservice has to be significantly smaller than what SOA tends to be and mainly is a small(er) independently deployable service. On the other hand, an SOA can be either a monolith or it can be comprised of multiple microservices.

Screen Shot 2016-05-29 at 12.36.46 PM.png
Figure 3: SOA and Microservices

It is also important that SOA has been designed and implemented in various styles which could be different with what it is described here, usually due to a focus on ESBs which is used to integrate monolithic applications.