Release 5.2
diff --git a/src/js/background.js b/src/js/background.js
new file mode 100644
index 0000000..e3c030e
--- /dev/null
+++ b/src/js/background.js
@@ -0,0 +1,323 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.  Use of this
+// source code is governed by a BSD-style license that can be found in the
+// LICENSE file.
+
+var screenshot = {
+  tab: 0,
+  canvas: document.createElement("canvas"),
+  startX: 0,
+  startY: 0,
+  scrollX: 0,
+  scrollY: 0,
+  docHeight: 0,
+  docWidth: 0,
+  visibleWidth: 0,
+  visibleHeight: 0,
+  scrollXCount: 0,
+  scrollYCount: 0,
+  scrollBarX: 17,
+  scrollBarY: 17,
+  captureStatus: true,
+  screenshotName: null,
+
+  handleHotKey: function(keyCode) {
+    if (HotKey.isEnabled()) {
+      switch (keyCode) {
+        case HotKey.getCharCode('area'):
+          screenshot.showSelectionArea();
+          break;
+        case HotKey.getCharCode('viewport'):
+          screenshot.captureWindow();
+          break;
+        case HotKey.getCharCode('fullpage'):
+          screenshot.captureWebpage();
+          break;
+        case HotKey.getCharCode('screen'):
+          screenshot.captureScreen();
+          break;
+      }
+    }
+  },
+
+  /**
+  * Receive messages from content_script, and then decide what to do next
+  */
+  addMessageListener: function() {
+    chrome.extension.onMessage.addListener(function(request, sender, response) {
+      var obj = request;
+      var hotKeyEnabled = HotKey.isEnabled();
+      switch (obj.msg) {
+        case 'capture_hot_key':
+          screenshot.handleHotKey(obj.keyCode);
+          break;
+        case 'capture_selected':
+          screenshot.captureSelected();
+          break;
+        case 'capture_window':
+          if (hotKeyEnabled) {
+            screenshot.captureWindow();
+          }
+          break;
+        case 'capture_area':
+          if (hotKeyEnabled) {
+            screenshot.showSelectionArea();
+          }
+          break;
+        case 'capture_webpage':
+          if (hotKeyEnabled) {
+            screenshot.captureWebpage();
+          }
+          break;
+      }
+    });
+  },
+
+  /**
+  * Send the Message to content-script
+  */
+  sendMessage: function(message, callback) {
+    chrome.tabs.getSelected(null, function(tab) {
+      chrome.tabs.sendMessage(tab.id, message, callback);
+    });
+  },
+
+  showSelectionArea: function() {
+    screenshot.sendMessage({msg: 'show_selection_area'}, null);
+  },
+
+  captureWindow: function() {
+    screenshot.sendMessage({msg: 'capture_window'},
+        screenshot.onResponseVisibleSize);
+  },
+
+  captureSelected: function() {
+    screenshot.sendMessage({msg: 'capture_selected'},
+        screenshot.onResponseVisibleSize);
+  },
+
+  captureWebpage: function() {
+    screenshot.sendMessage({msg: 'scroll_init'},
+        screenshot.onResponseVisibleSize);
+  },
+
+  onResponseVisibleSize: function(response) {
+    switch (response.msg) {
+      case 'capture_window':
+        screenshot.captureVisible(response.docWidth, response.docHeight);
+        break;
+      case 'scroll_init_done':
+        screenshot.startX = response.startX,
+        screenshot.startY = response.startY,
+        screenshot.scrollX = response.scrollX,
+        screenshot.scrollY = response.scrollY,
+        screenshot.canvas.width = response.canvasWidth;
+        screenshot.canvas.height = response.canvasHeight;
+        screenshot.visibleHeight = response.visibleHeight,
+        screenshot.visibleWidth = response.visibleWidth,
+        screenshot.scrollXCount = response.scrollXCount;
+        screenshot.scrollYCount = response.scrollYCount;
+        screenshot.docWidth = response.docWidth;
+        screenshot.docHeight = response.docHeight;
+        screenshot.zoom = response.zoom;
+        setTimeout("screenshot.captureAndScroll()", 100);
+        break;
+      case 'scroll_next_done':
+        screenshot.scrollXCount = response.scrollXCount;
+        screenshot.scrollYCount = response.scrollYCount;
+        setTimeout("screenshot.captureAndScroll()", 100);
+        break;
+      case 'scroll_finished':
+        screenshot.captureAndScrollDone();
+        break;
+    }
+  },
+
+  captureSpecialPage: function() {
+    var formatParam = localStorage.screenshootQuality || 'png';
+    chrome.tabs.captureVisibleTab(
+        null, {format: formatParam, quality: 50}, function(data) {
+      var image = new Image();
+      image.onload = function() {
+        screenshot.canvas.width = image.width;
+        screenshot.canvas.height = image.height;
+        var context = screenshot.canvas.getContext("2d");
+        context.drawImage(image, 0, 0);
+        screenshot.postImage();
+      };
+      image.src = data;
+    });
+  },
+
+  captureScreenCallback: function(data) {
+    var image = new Image();
+    image.onload = function() {
+      screenshot.canvas.width = image.width;
+      screenshot.canvas.height = image.height;
+      var context = screenshot.canvas.getContext("2d");
+      context.drawImage(image, 0, 0);
+      screenshot.postImage();
+    };
+    image.src = "data:image/bmp;base64," + data;
+  },
+
+  /**
+  * Use drawImage method to slice parts of a source image and draw them to
+  * the canvas
+  */
+  capturePortion: function(x, y, width, height,
+                           visibleWidth, visibleHeight, docWidth, docHeight) {
+    var formatParam = localStorage.screenshootQuality || 'png';
+    chrome.tabs.captureVisibleTab(
+        null, {format: formatParam, quality: 50}, function(data) {
+      var image = new Image();
+      image.onload = function() {
+        var curHeight = image.width < docWidth ?
+            image.height - screenshot.scrollBarY : image.height;
+        var curWidth = image.height < docHeight ?
+            image.width - screenshot.scrollBarX : image.width;
+        var zoomX = curWidth / visibleWidth;
+        var zoomY = curHeight / visibleHeight;
+        screenshot.canvas.width = width * zoomX;
+        screenshot.canvas.height = height * zoomY;
+        var context = screenshot.canvas.getContext("2d");
+        context.drawImage(image, x * zoomX, y * zoomY, width * zoomX,
+            height * zoomY, 0, 0, width * zoomX, height * zoomY);
+        screenshot.postImage();
+      };
+      image.src = data;
+    });
+  },
+
+  captureVisible: function(docWidth, docHeight) {
+    var formatParam = localStorage.screenshootQuality || 'png';
+    chrome.tabs.captureVisibleTab(
+        null, {format: formatParam, quality: 50}, function(data) {
+      var image = new Image();
+      image.onload = function() {
+        var width = image.height < docHeight ?
+            image.width - 17 : image.width;
+        var height = image.width < docWidth ?
+            image.height - 17 : image.height;
+        screenshot.canvas.width = width;
+        screenshot.canvas.height = height;
+        var context = screenshot.canvas.getContext("2d");
+        context.drawImage(image, 0, 0, width, height, 0, 0, width, height);
+        screenshot.postImage();
+      };
+      image.src = data;
+    });
+  },
+
+  /**
+  * Use the drawImage method to stitching images, and render to canvas
+  */
+  captureAndScroll: function() {
+    var formatParam = localStorage.screenshootQuality || 'png';
+    chrome.tabs.captureVisibleTab(
+        null, {format: formatParam, quality: 50}, function(data) {
+      var image = new Image();
+      image.onload = function() {
+        var context = screenshot.canvas.getContext('2d');
+        var width = 0;
+        var height = 0;
+
+        // Get scroll bar's width.
+        screenshot.scrollBarY =
+            screenshot.visibleHeight < screenshot.docHeight ? 17 : 0;
+        screenshot.scrollBarX =
+            screenshot.visibleWidth < screenshot.docWidth ? 17 : 0;
+
+        // Get visible width and height of capture result.
+        var visibleWidth =
+            (image.width - screenshot.scrollBarY < screenshot.canvas.width ?
+            image.width - screenshot.scrollBarY : screenshot.canvas.width);
+        var visibleHeight =
+            (image.height - screenshot.scrollBarX < screenshot.canvas.height ?
+            image.height - screenshot.scrollBarX : screenshot.canvas.height);
+
+        // Get region capture start x coordinate.
+        var zoom = screenshot.zoom;
+        var x1 = screenshot.startX - Math.round(screenshot.scrollX * zoom);
+        var x2 = 0;
+        var y1 = screenshot.startY - Math.round(screenshot.scrollY * zoom);
+        var y2 = 0;
+
+        if ((screenshot.scrollYCount + 1) * visibleWidth >
+            screenshot.canvas.width) {
+          width = screenshot.canvas.width % visibleWidth;
+          x1 = (screenshot.scrollYCount + 1) * visibleWidth -
+              screenshot.canvas.width + screenshot.startX - screenshot.scrollX;
+        } else {
+          width = visibleWidth;
+        }
+
+        if ((screenshot.scrollXCount + 1) * visibleHeight >
+            screenshot.canvas.height) {
+          height = screenshot.canvas.height % visibleHeight;
+          if ((screenshot.scrollXCount + 1) * visibleHeight +
+              screenshot.scrollY < screenshot.docHeight) {
+            y1 = 0;
+          } else {
+            y1 = (screenshot.scrollXCount + 1) * visibleHeight +
+                screenshot.scrollY - screenshot.docHeight;
+          }
+
+        } else {
+          height = visibleHeight;
+        }
+        x2 = screenshot.scrollYCount * visibleWidth;
+        y2 = screenshot.scrollXCount * visibleHeight;
+        context.drawImage(image, x1, y1, width, height, x2, y2, width, height);
+        screenshot.sendMessage({msg: 'scroll_next', visibleWidth: visibleWidth,
+            visibleHeight: visibleHeight}, screenshot.onResponseVisibleSize);
+      };
+      image.src = data;
+    });
+  },
+
+  captureAndScrollDone: function() {
+    screenshot.postImage();
+  },
+
+  /**
+  * Post the image to 'showimage.html'
+  */
+  postImage: function() {
+    chrome.tabs.getSelected(null, function(tab) {
+      screenshot.tab = tab;
+    });
+    var date = new Date();
+    screenshot.screenshotName = "Screenshot "+dateFormat(date, 'Y-m-d H.i.s');
+    chrome.tabs.create({'url': 'showimage.html'});
+    var popup = chrome.extension.getViews({type: 'popup'})[0];
+    if (popup)
+      popup.close();
+  },
+
+  isThisPlatform: function(operationSystem) {
+    return navigator.userAgent.toLowerCase().indexOf(operationSystem) > -1;
+  },
+
+  executeScriptsInExistingTabs: function() {
+    chrome.windows.getAll(null, function(wins) {
+      for (var j = 0; j < wins.length; ++j) {
+        chrome.tabs.getAllInWindow(wins[j].id, function(tabs) {
+          for (var i = 0; i < tabs.length; ++i) {
+            if (tabs[i].url.indexOf("chrome://") != 0) {
+              chrome.tabs.executeScript(tabs[i].id, { file: 'js/page.js' });
+              chrome.tabs.executeScript(tabs[i].id, { file: 'js/shortcut.js' });
+            }
+          }
+        });
+      }
+    });
+  },
+
+  init: function() {
+    localStorage.screenshootQuality = localStorage.screenshootQuality || 'png';
+    screenshot.executeScriptsInExistingTabs();
+    screenshot.addMessageListener();
+  }
+};
+
+screenshot.init();