summaryrefslogtreecommitdiffstats
path: root/chrome/common/extensions/docs/examples/api
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2010-10-27 13:32:00 +0100
committerKristian Monsen <kristianm@google.com>2010-10-27 13:33:18 +0100
commit8ae428e0fb7feea16d79853f29447469a93bedff (patch)
tree055de38ae24a222549cf0c8e4f68f2e679388551 /chrome/common/extensions/docs/examples/api
parentfb45465643e6355ea14862fb898dcb4b51175bea (diff)
downloadexternal_chromium-8ae428e0fb7feea16d79853f29447469a93bedff.zip
external_chromium-8ae428e0fb7feea16d79853f29447469a93bedff.tar.gz
external_chromium-8ae428e0fb7feea16d79853f29447469a93bedff.tar.bz2
Adding missing files to chrome/common
Again, not used but added to make merges easier Change-Id: If11539b063fdf39e8ca7e82d5c7b642d512e8f12
Diffstat (limited to 'chrome/common/extensions/docs/examples/api')
-rw-r--r--chrome/common/extensions/docs/examples/api/bookmarks/basic.zipbin0 -> 5647 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/bookmarks/basic/manifest.json13
-rw-r--r--chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html139
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/make_page_red.zipbin0 -> 3930 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/make_page_red/background.html18
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/make_page_red/icon.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/make_page_red/manifest.json12
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/print.zipbin0 -> 1614 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/print/background.html12
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/print/manifest.json13
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/print/print_16x16.pngbin0 -> 647 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_icon_path.zipbin0 -> 15530 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/background.html20
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon1.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon2.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon3.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon4.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon5.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/manifest.json11
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_page_color.zipbin0 -> 5245 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_page_color/icon.pngbin0 -> 3622 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_page_color/manifest.json12
-rw-r--r--chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.html53
-rw-r--r--chrome/common/extensions/docs/examples/api/contextMenus/basic.zipbin0 -> 3512 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/contextMenus/basic/background.html1
-rw-r--r--chrome/common/extensions/docs/examples/api/contextMenus/basic/manifest.json7
-rw-r--r--chrome/common/extensions/docs/examples/api/contextMenus/basic/sample.js69
-rw-r--r--chrome/common/extensions/docs/examples/api/cookies.zipbin0 -> 9255 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/cookies/background.html33
-rw-r--r--chrome/common/extensions/docs/examples/api/cookies/cookie.pngbin0 -> 719 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/cookies/manager.html297
-rw-r--r--chrome/common/extensions/docs/examples/api/cookies/manifest.json11
-rw-r--r--chrome/common/extensions/docs/examples/api/history/showHistory.zipbin0 -> 9608 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/history/showHistory/clock.pngbin0 -> 4984 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/history/showHistory/manifest.json10
-rw-r--r--chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.html15
-rw-r--r--chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.js113
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/cld.zipbin0 -> 1310 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/cld/background.html32
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/cld/manifest.json12
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/getMessage.zipbin0 -> 6739 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/en_US/messages.json27
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/es/messages.json27
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/sr/messages.json24
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/getMessage/icon.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/getMessage/manifest.json11
-rw-r--r--chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.html38
-rw-r--r--chrome/common/extensions/docs/examples/api/idle/idle_simple.zipbin0 -> 11992 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/idle/idle_simple/background.html34
-rw-r--r--chrome/common/extensions/docs/examples/api/idle/idle_simple/history.html118
-rw-r--r--chrome/common/extensions/docs/examples/api/idle/idle_simple/manifest.json15
-rw-r--r--chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-128.pngbin0 -> 3466 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-16.pngbin0 -> 713 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-19.pngbin0 -> 309 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-48.pngbin0 -> 1347 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/infobars/sandwichbar.zipbin0 -> 16055 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/infobars/sandwichbar/background.html34
-rw-r--r--chrome/common/extensions/docs/examples/api/infobars/sandwichbar/contentscript.js13
-rw-r--r--chrome/common/extensions/docs/examples/api/infobars/sandwichbar/infobar.html42
-rw-r--r--chrome/common/extensions/docs/examples/api/infobars/sandwichbar/manifest.json20
-rw-r--r--chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-128.pngbin0 -> 8078 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-16.pngbin0 -> 708 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-19.pngbin0 -> 657 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-48.pngbin0 -> 2621 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/messaging/timer.zipbin0 -> 3558 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/messaging/timer/clock.pngbin0 -> 383 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/messaging/timer/manifest.json17
-rw-r--r--chrome/common/extensions/docs/examples/api/messaging/timer/page.js10
-rw-r--r--chrome/common/extensions/docs/examples/api/messaging/timer/popup.html77
-rw-r--r--chrome/common/extensions/docs/examples/api/notifications.zipbin0 -> 49949 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/notifications/128.pngbin0 -> 22858 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/notifications/16.pngbin0 -> 3592 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/notifications/48.pngbin0 -> 7366 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/notifications/64.pngbin0 -> 9899 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/notifications/background.html58
-rw-r--r--chrome/common/extensions/docs/examples/api/notifications/error.html41
-rw-r--r--chrome/common/extensions/docs/examples/api/notifications/manifest.json10
-rw-r--r--chrome/common/extensions/docs/examples/api/notifications/options.html85
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox.zipbin0 -> 1101 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/background.html19
-rw-r--r--chrome/common/extensions/docs/examples/api/omnibox/manifest.json7
-rw-r--r--chrome/common/extensions/docs/examples/api/override/blank_ntp.zipbin0 -> 699 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/override/blank_ntp/blank.html19
-rw-r--r--chrome/common/extensions/docs/examples/api/override/blank_ntp/manifest.json8
-rw-r--r--chrome/common/extensions/docs/examples/api/override/override_igoogle.zipbin0 -> 496 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/override/override_igoogle/manifest.json7
-rw-r--r--chrome/common/extensions/docs/examples/api/override/override_igoogle/redirect.html3
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content.zipbin0 -> 14181 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/background.html25
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/contentscript.js14
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/manifest.json26
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-128.pngbin0 -> 8078 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-19.pngbin0 -> 657 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-48.pngbin0 -> 2621 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url.zipbin0 -> 15175 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/background.html23
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-128.pngbin0 -> 10219 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-19.pngbin0 -> 809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-48.pngbin0 -> 2366 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/manifest.json18
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/set_icon.zipbin0 -> 8421 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.html69
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon1.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon2.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/pageAction/set_icon/manifest.json10
-rw-r--r--chrome/common/extensions/docs/examples/api/processes/show_tabs.zipbin0 -> 6137 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/processes/show_tabs/icon.pngbin0 -> 2809 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/processes/show_tabs/manifest.json13
-rw-r--r--chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.html92
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/inspector.zipbin0 -> 46521 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/inspector/background.html5
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/inspector/jstemplate_compiled.js1182
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/inspector/manifest.json10
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.html389
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/screenshot.zipbin0 -> 6202 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/screenshot/background.html10
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/screenshot/camera.pngbin0 -> 1257 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json11
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.html14
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.js48
-rw-r--r--chrome/common/extensions/docs/examples/api/tabs/screenshot/white.pngbin0 -> 1614 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/windows/merge_windows.zipbin0 -> 12134 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/windows/merge_windows/NOTICE2
-rw-r--r--chrome/common/extensions/docs/examples/api/windows/merge_windows/arrow_in.pngbin0 -> 600 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/windows/merge_windows/background.html49
-rw-r--r--chrome/common/extensions/docs/examples/api/windows/merge_windows/manifest.json15
-rw-r--r--chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_128.pngbin0 -> 6583 bytes
-rw-r--r--chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_48.pngbin0 -> 2359 bytes
128 files changed, 3692 insertions, 0 deletions
diff --git a/chrome/common/extensions/docs/examples/api/bookmarks/basic.zip b/chrome/common/extensions/docs/examples/api/bookmarks/basic.zip
new file mode 100644
index 0000000..7460329
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/bookmarks/basic.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/bookmarks/basic/manifest.json b/chrome/common/extensions/docs/examples/api/bookmarks/basic/manifest.json
new file mode 100644
index 0000000..1dc28ab
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/bookmarks/basic/manifest.json
@@ -0,0 +1,13 @@
+{
+ "name": "My Bookmarks",
+ "version": "1.0",
+ "description": "A browser action with a popup dump of all bookmarks, including search, add, edit and delete.",
+ "permissions": [
+ "bookmarks", "tabs"
+ ],
+ "browser_action": {
+ "default_title": "My Bookmarks.",
+ "default_icon": "icon.png",
+ "popup": "popup.html"
+ }
+} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html b/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html
new file mode 100644
index 0000000..00919c2
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/bookmarks/basic/popup.html
@@ -0,0 +1,139 @@
+<html>
+<head>
+<link type="text/css" href="http://jqueryui.com/themes/base/ui.all.css" rel="stylesheet">
+<style>
+div, td, th { color: black; }
+</style>
+<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
+<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"></script>
+<script>
+ // Search the bookmarks when entering the search keyword.
+ $(function() {
+ $('#search').change(function() {
+ $('#bookmarks').empty();
+ dumpBookmarks($('#search').val());
+ });
+ });
+ // Traverse the bookmark tree, and print the folder and nodes.
+ function dumpBookmarks(query) {
+ var bookmarkTreeNodes = chrome.bookmarks.getTree(
+ function(bookmarkTreeNodes) {
+ $('#bookmarks').append(dumpTreeNodes(bookmarkTreeNodes, query));
+ });
+ }
+ function dumpTreeNodes(bookmarkNodes, query) {
+ var list = $('<ul>');
+ var i;
+ for (i = 0; i < bookmarkNodes.length; i++) {
+ list.append(dumpNode(bookmarkNodes[i], query));
+ }
+ return list;
+ }
+ function dumpNode(bookmarkNode, query) {
+ if (bookmarkNode.title) {
+ if (query && !bookmarkNode.children) {
+ if (String(bookmarkNode.title).indexOf(query) == -1) {
+ return $('<span></span>');
+ }
+ }
+ var anchor = $('<a>');
+ anchor.attr('href', bookmarkNode.url);
+ anchor.text(bookmarkNode.title);
+ /*
+ * When clicking on a bookmark in the extension, a new tab is fired with
+ * the bookmark url.
+ */
+ anchor.click(function() {
+ chrome.tabs.create({url: bookmarkNode.url});
+ });
+ var span = $('<span>');
+ var options = bookmarkNode.children ?
+ $('<span>[<a href="#" id='addlink'>Add</a>]</span>') :
+ $('<span>[<a id="editlink" href="#">Edit</a> <a id="deletelink" ' +
+ 'href="#">Delete</a>]</span>');
+ var edit = bookmarkNode.children ? $('<table><tr><td>Name</td><td>' +
+ '<input id="title"></td></tr><tr><td>URL</td><td><input id="url">' +
+ '</td></tr></table>') : $('<input>');
+ // Show add and edit links when hover over.
+ span.hover(function() {
+ span.append(options);
+ $('#deletelink').click(function() {
+ $('#deletedialog').empty().dialog({
+ autoOpen: false,
+ title: 'Confirm Deletion',
+ resizable: false,
+ height: 140,
+ modal: true,
+ overlay: {
+ backgroundColor: '#000',
+ opacity: 0.5
+ },
+ buttons: {
+ 'Yes, Delete It!': function() {
+ chrome.bookmarks.remove(String(bookmarkNode.id));
+ span.parent().remove();
+ $(this).dialog('destroy');
+ },
+ Cancel: function() {
+ $(this).dialog('destroy');
+ }
+ }
+ }).dialog('open');
+ });
+ $('#addlink').click(function() {
+ $('#adddialog').empty().append(edit).dialog({autoOpen: false,
+ closeOnEscape: true, title: 'Add New Bookmark', modal: true,
+ buttons: {
+ 'Add' : function() {
+ chrome.bookmarks.create({parentId: bookmarkNode.id,
+ title: $('#title').val(), url: $('#url').val()});
+ $('#bookmarks').empty();
+ $(this).dialog('destroy');
+ window.dumpBookmarks();
+ },
+ 'Cancel': function() {
+ $(this).dialog('destroy');
+ }
+ }}).dialog('open');
+ });
+ $('#editlink').click(function() {
+ edit.val(anchor.text());
+ $('#editdialog').empty().append(edit).dialog({autoOpen: false,
+ closeOnEscape: true, title: 'Edit Title', modal: true,
+ show: 'slide', buttons: {
+ 'Save': function() {
+ chrome.bookmarks.update(String(bookmarkNode.id), {
+ title: edit.val()
+ });
+ anchor.text(edit.val());
+ options.show();
+ $(this).dialog('destroy');
+ },
+ 'Cancel': function() {
+ $(this).dialog('destroy');
+ }
+ }}).dialog('open');
+ });
+ options.fadeIn();
+ },
+ // unhover
+ function() {
+ options.remove();
+ }).append(anchor);
+ }
+ var li = $(bookmarkNode.title ? '<li>' : '<div>').append(span);
+ if (bookmarkNode.children && bookmarkNode.children.length > 0) {
+ li.append(dumpTreeNodes(bookmarkNode.children, query));
+ }
+ return li;
+ }
+</script>
+</head>
+<body onload="dumpBookmarks();" style="width: 400px">
+<div>Search Bookmarks: <input id="search"></div>
+<div id="bookmarks"></div>
+<div id="editdialog"></div>
+<div id="deletedialog"></div>
+<div id="adddialog"></div>
+</body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/make_page_red.zip b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red.zip
new file mode 100644
index 0000000..ac58aa1
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/background.html b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/background.html
new file mode 100644
index 0000000..875ea31
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/background.html
@@ -0,0 +1,18 @@
+<html>
+<head>
+<script>
+ // Called when the user clicks on the browser action.
+ chrome.browserAction.onClicked.addListener(function(tab) {
+ chrome.tabs.executeScript(null, {code:"document.body.bgColor='red'"});
+ });
+
+ chrome.browserAction.setBadgeBackgroundColor({color:[0, 200, 0, 100]});
+
+ var i = 0;
+ window.setInterval(function() {
+ chrome.browserAction.setBadgeText({text:String(i)});
+ i++;
+ }, 10);
+</script>
+</head>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/icon.png b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/icon.png
new file mode 100644
index 0000000..9a79a46
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/icon.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/manifest.json b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/manifest.json
new file mode 100644
index 0000000..6bb35c6
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/manifest.json
@@ -0,0 +1,12 @@
+{
+ "name": "A browser action with no icon that makes the page red",
+ "version": "1.0",
+ "background_page": "background.html",
+ "permissions": [
+ "tabs", "http://*/*"
+ ],
+ "browser_action": {
+ "name": "Make this page red",
+ "icons": ["icon.png"]
+ }
+} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/print.zip b/chrome/common/extensions/docs/examples/api/browserAction/print.zip
new file mode 100644
index 0000000..95c9329
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/print.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/print/background.html b/chrome/common/extensions/docs/examples/api/browserAction/print/background.html
new file mode 100644
index 0000000..5b3f930
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/print/background.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<script>
+ // Called when the user clicks on the browser action.
+ chrome.browserAction.onClicked.addListener(function(tab) {
+ var action_url = "javascript:window.print();";
+ chrome.tabs.update(tab.id, {url: action_url});
+ });
+</script>
+</head>
+</html>
+
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/print/manifest.json b/chrome/common/extensions/docs/examples/api/browserAction/print/manifest.json
new file mode 100644
index 0000000..0949549
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/print/manifest.json
@@ -0,0 +1,13 @@
+{
+ "name": "Print this page",
+ "description": "Adds a print button to the browser.",
+ "version": "1.1",
+ "background_page": "background.html",
+ "permissions": [
+ "tabs", "http://*/*", "https://*/*"
+ ],
+ "browser_action": {
+ "default_title": "Print this page",
+ "default_icon": "print_16x16.png"
+ }
+} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/print/print_16x16.png b/chrome/common/extensions/docs/examples/api/browserAction/print/print_16x16.png
new file mode 100644
index 0000000..d145964
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/print/print_16x16.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path.zip b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path.zip
new file mode 100644
index 0000000..f424d96
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/background.html b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/background.html
new file mode 100644
index 0000000..11aea5a
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/background.html
@@ -0,0 +1,20 @@
+<html>
+<head>
+<script>
+ var min = 1;
+ var max = 5;
+ var current = min;
+
+ function updateIcon() {
+ chrome.browserAction.setIcon({path:"icon" + current + ".png"});
+ current++;
+
+ if (current > max)
+ current = min;
+ }
+
+ chrome.browserAction.onClicked.addListener(updateIcon);
+ updateIcon();
+</script>
+</head>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon1.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon1.png
new file mode 100644
index 0000000..9a79a46
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon1.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon2.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon2.png
new file mode 100644
index 0000000..8d3f710
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon2.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon3.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon3.png
new file mode 100644
index 0000000..2d9dec3
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon3.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon4.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon4.png
new file mode 100644
index 0000000..896fc36
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon4.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon5.png b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon5.png
new file mode 100644
index 0000000..a5afa25
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon5.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/manifest.json b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/manifest.json
new file mode 100644
index 0000000..ea83de7
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/manifest.json
@@ -0,0 +1,11 @@
+{
+ "name": "A browser action which changes its icon when clicked.",
+ "version": "1.0",
+ "background_page": "background.html",
+ "permissions": [
+ "tabs", "http://*/*"
+ ],
+ "browser_action": {
+ "name": "Click to change the icon's color"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color.zip b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color.zip
new file mode 100644
index 0000000..e76e94b
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/icon.png b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/icon.png
new file mode 100644
index 0000000..1f1c906
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/icon.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/manifest.json b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/manifest.json
new file mode 100644
index 0000000..83e9052
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/manifest.json
@@ -0,0 +1,12 @@
+{
+ "name": "A browser action with a popup that changes the page color.",
+ "version": "1.0",
+ "permissions": [
+ "tabs", "http://*/*", "https://*/*"
+ ],
+ "browser_action": {
+ "default_title": "Set this page's color.",
+ "default_icon": "icon.png",
+ "popup": "popup.html"
+ }
+} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.html b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.html
new file mode 100644
index 0000000..9230254
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/popup.html
@@ -0,0 +1,53 @@
+<style>
+body {
+ overflow: hidden;
+ margin: 0px;
+ padding: 0px;
+ background: white;
+}
+
+div:first-child {
+ margin-top: 0px;
+}
+
+div {
+ cursor: pointer;
+ text-align: center;
+ padding: 1px 3px;
+ font-family: sans-serif;
+ font-size: 0.8em;
+ width: 100px;
+ margin-top: 1px;
+ background: #cccccc;
+}
+div:hover {
+ background: #aaaaaa;
+}
+#red {
+ border: 1px solid red;
+ color: red;
+}
+#blue {
+ border: 1px solid blue;
+ color: blue;
+}
+#green {
+ border: 1px solid green;
+ color: green;
+}
+#yellow {
+ border: 1px solid yellow;
+ color: yellow;
+}
+</style>
+<script>
+function click(color) {
+ chrome.tabs.executeScript(null,
+ {code:"document.body.style.backgroundColor='" + color.id + "'"});
+ window.close();
+}
+</script>
+<div onclick="click(this)" id="red">red</div>
+<div onclick="click(this)" id="blue">blue</div>
+<div onclick="click(this)" id="green">green</div>
+<div onclick="click(this)" id="yellow">yellow</div>
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/basic.zip b/chrome/common/extensions/docs/examples/api/contextMenus/basic.zip
new file mode 100644
index 0000000..443d83b
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/contextMenus/basic.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/basic/background.html b/chrome/common/extensions/docs/examples/api/contextMenus/basic/background.html
new file mode 100644
index 0000000..8fc4efe
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/contextMenus/basic/background.html
@@ -0,0 +1 @@
+<script src="sample.js"></script>
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/basic/manifest.json b/chrome/common/extensions/docs/examples/api/contextMenus/basic/manifest.json
new file mode 100644
index 0000000..bc6fb3f
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/contextMenus/basic/manifest.json
@@ -0,0 +1,7 @@
+{
+ "name": "Context Menus Sample",
+ "description": "Shows some of the features of the Context Menus API",
+ "version": "0.5",
+ "permissions": ["contextMenus"],
+ "background_page": "background.html"
+}
diff --git a/chrome/common/extensions/docs/examples/api/contextMenus/basic/sample.js b/chrome/common/extensions/docs/examples/api/contextMenus/basic/sample.js
new file mode 100644
index 0000000..a58be3a
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/contextMenus/basic/sample.js
@@ -0,0 +1,69 @@
+// Copyright (c) 2010 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.
+
+// A generic onclick callback function.
+function genericOnClick(info, tab) {
+ console.log("item " + info.menuItemId + " was clicked");
+ console.log("info: " + JSON.stringify(info));
+ console.log("tab: " + JSON.stringify(tab));
+}
+
+// Create one test item for each context type.
+var contexts = ["page","selection","link","editable","image","video",
+ "audio"];
+for (var i = 0; i < contexts.length; i++) {
+ var context = contexts[i];
+ var title = "Test '" + context + "' menu item";
+ var id = chrome.contextMenus.create({"title": title, "contexts":[context],
+ "onclick": genericOnClick});
+ console.log("'" + context + "' item:" + id);
+}
+
+
+// Create a parent item and two children.
+var parent = chrome.contextMenus.create({"title": "Test parent item"});
+var child1 = chrome.contextMenus.create(
+ {"title": "Child 1", "parentId": parent, "onclick": genericOnClick});
+var child2 = chrome.contextMenus.create(
+ {"title": "Child 2", "parentId": parent, "onclick": genericOnClick});
+console.log("parent:" + parent + " child1:" + child1 + " child2:" + child2);
+
+
+// Create some radio items.
+function radioOnClick(info, tab) {
+ console.log("radio item " + info.menuItemId +
+ " was clicked (previous checked state was " +
+ info.wasChecked + ")");
+}
+var radio1 = chrome.contextMenus.create({"title": "Radio 1", "type": "radio",
+ "onclick":radioOnClick});
+var radio2 = chrome.contextMenus.create({"title": "Radio 2", "type": "radio",
+ "onclick":radioOnClick});
+console.log("radio1:" + radio1 + " radio2:" + radio2);
+
+
+// Create some checkbox items.
+function checkboxOnClick(info, tab) {
+ console.log(JSON.stringify(info));
+ console.log("checkbox item " + info.menuItemId +
+ " was clicked, state is now: " + info.checked +
+ "(previous state was " + info.wasChecked + ")");
+
+}
+var checkbox1 = chrome.contextMenus.create(
+ {"title": "Checkbox1", "type": "checkbox", "onclick":checkboxOnClick});
+var checkbox2 = chrome.contextMenus.create(
+ {"title": "Checkbox2", "type": "checkbox", "onclick":checkboxOnClick});
+console.log("checkbox1:" + checkbox1 + " checkbox2:" + checkbox2);
+
+
+// Intentionally create an invalid item, to show off error checking in the
+// create callback.
+console.log("About to try creating an invalid item - an error about " +
+ "item 999 should show up");
+chrome.contextMenus.create({"title": "Oops", "parentId":999}, function() {
+ if (chrome.extension.lastError) {
+ console.log("Got expected error: " + chrome.extension.lastError.message);
+ }
+});
diff --git a/chrome/common/extensions/docs/examples/api/cookies.zip b/chrome/common/extensions/docs/examples/api/cookies.zip
new file mode 100644
index 0000000..edd8163
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/cookies.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/cookies/background.html b/chrome/common/extensions/docs/examples/api/cookies/background.html
new file mode 100644
index 0000000..8cf522f
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/cookies/background.html
@@ -0,0 +1,33 @@
+<script>
+
+chrome.cookies.onChanged.addListener(function(info) {
+ console.log("onChanged" + JSON.stringify(info));
+});
+
+function focusOrCreateTab(url) {
+ chrome.windows.getAll({"populate":true}, function(windows) {
+ var existing_tab = null;
+ for (var i in windows) {
+ var tabs = windows[i].tabs;
+ for (var j in tabs) {
+ var tab = tabs[j];
+ if (tab.url == url) {
+ existing_tab = tab;
+ break;
+ }
+ }
+ }
+ if (existing_tab) {
+ chrome.tabs.update(existing_tab.id, {"selected":true});
+ } else {
+ chrome.tabs.create({"url":url, "selected":true});
+ }
+ });
+}
+
+chrome.browserAction.onClicked.addListener(function(tab) {
+ var manager_url = chrome.extension.getURL("manager.html");
+ focusOrCreateTab(manager_url);
+});
+
+</script>
diff --git a/chrome/common/extensions/docs/examples/api/cookies/cookie.png b/chrome/common/extensions/docs/examples/api/cookies/cookie.png
new file mode 100644
index 0000000..ca72eca
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/cookies/cookie.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/cookies/manager.html b/chrome/common/extensions/docs/examples/api/cookies/manager.html
new file mode 100644
index 0000000..8c644c9
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/cookies/manager.html
@@ -0,0 +1,297 @@
+<html>
+<head>
+<style>
+table {
+ border-collapse:collapse;
+}
+
+td {
+ border: 1px solid black;
+ padding-left: 5px;
+}
+
+td.button {
+ border: none;
+}
+
+td.cookie_count {
+ text-align: right;
+}
+
+</style>
+
+<script>
+
+if (!chrome.cookies) {
+ chrome.cookies = chrome.experimental.cookies;
+}
+
+// A simple Timer class.
+function Timer() {
+ this.start_ = new Date();
+
+ this.elapsed = function() {
+ return (new Date()) - this.start_;
+ }
+
+ this.reset = function() {
+ this.start_ = new Date();
+ }
+}
+
+// Compares cookies for "key" (name, domain, etc.) equality, but not "value"
+// equality.
+function cookieMatch(c1, c2) {
+ return (c1.name == c2.name) && (c1.domain == c2.domain) &&
+ (c1.hostOnly == c2.hostOnly) && (c1.path == c2.path) &&
+ (c1.secure == c2.secure) && (c1.httpOnly == c2.httpOnly) &&
+ (c1.session == c2.session) && (c1.storeId == c2.storeId);
+}
+
+// Returns an array of sorted keys from an associative array.
+function sortedKeys(array) {
+ var keys = [];
+ for (var i in array) {
+ keys.push(i);
+ }
+ keys.sort();
+ return keys;
+}
+
+// Shorthand for document.querySelector.
+function select(selector) {
+ return document.querySelector(selector);
+}
+
+// An object used for caching data about the browser's cookies, which we update
+// as notifications come in.
+function CookieCache() {
+ this.cookies_ = {};
+
+ this.reset = function() {
+ this.cookies_ = {};
+ }
+
+ this.add = function(cookie) {
+ var domain = cookie.domain;
+ if (!this.cookies_[domain]) {
+ this.cookies_[domain] = [];
+ }
+ this.cookies_[domain].push(cookie);
+ };
+
+ this.remove = function(cookie) {
+ var domain = cookie.domain;
+ if (this.cookies_[domain]) {
+ var i = 0;
+ while (i < this.cookies_[domain].length) {
+ if (cookieMatch(this.cookies_[domain][i], cookie)) {
+ this.cookies_[domain].splice(i, 1);
+ } else {
+ i++;
+ }
+ }
+ if (this.cookies_[domain].length == 0) {
+ delete this.cookies_[domain];
+ }
+ }
+ };
+
+ // Returns a sorted list of cookie domains that match |filter|. If |filter| is
+ // null, returns all domains.
+ this.getDomains = function(filter) {
+ var result = [];
+ sortedKeys(this.cookies_).forEach(function(domain) {
+ if (!filter || domain.indexOf(filter) != -1) {
+ result.push(domain);
+ }
+ });
+ return result;
+ }
+
+ this.getCookies = function(domain) {
+ return this.cookies_[domain];
+ };
+}
+
+
+var cache = new CookieCache();
+
+
+function removeAllForFilter() {
+ var filter = select("#filter").value;
+ var timer = new Timer();
+ cache.getDomains(filter).forEach(function(domain) {
+ removeCookiesForDomain(domain);
+ });
+}
+
+function removeAll() {
+ var all_cookies = [];
+ cache.getDomains().forEach(function(domain) {
+ cache.getCookies(domain).forEach(function(cookie) {
+ all_cookies.push(cookie);
+ });
+ });
+ cache.reset();
+ var count = all_cookies.length;
+ var timer = new Timer();
+ for (var i = 0; i < count; i++) {
+ removeCookie(all_cookies[i]);
+ }
+ timer.reset();
+ chrome.cookies.getAll({}, function(cookies) {
+ for (var i in cookies) {
+ cache.add(cookies[i]);
+ removeCookie(cookies[i]);
+ }
+ });
+}
+
+function removeCookie(cookie) {
+ var url = "http" + (cookie.secure ? "s" : "") + "://" + cookie.domain +
+ cookie.path;
+ chrome.cookies.remove({"url": url, "name": cookie.name});
+}
+
+function removeCookiesForDomain(domain) {
+ var timer = new Timer();
+ cache.getCookies(domain).forEach(function(cookie) {
+ removeCookie(cookie);
+ });
+}
+
+function resetTable() {
+ var table = select("#cookies");
+ while (table.rows.length > 1) {
+ table.deleteRow(table.rows.length - 1);
+ }
+}
+
+var reload_scheduled = false;
+
+function scheduleReloadCookieTable() {
+ if (!reload_scheduled) {
+ reload_scheduled = true;
+ setTimeout(reloadCookieTable, 250);
+ }
+}
+
+function reloadCookieTable() {
+ reload_scheduled = false;
+
+ var filter = select("#filter").value;
+
+ var domains = cache.getDomains(filter);
+
+ select("#filter_count").innerText = domains.length;
+ select("#total_count").innerText = cache.getDomains().length;
+
+ select("#delete_all_button").innerHTML = "";
+ if (domains.length) {
+ var button = document.createElement("button");
+ button.onclick = removeAllForFilter;
+ button.innerText = "delete all " + domains.length;
+ select("#delete_all_button").appendChild(button);
+ }
+
+ resetTable();
+ var table = select("#cookies");
+
+ domains.forEach(function(domain) {
+ var cookies = cache.getCookies(domain);
+ var row = table.insertRow(-1);
+ row.insertCell(-1).innerText = domain;
+ var cell = row.insertCell(-1);
+ cell.innerText = cookies.length;
+ cell.setAttribute("class", "cookie_count");
+
+ var button = document.createElement("button");
+ button.innerText = "delete";
+ button.onclick = (function(dom){
+ return function() {
+ removeCookiesForDomain(dom);
+ };
+ }(domain));
+ var cell = row.insertCell(-1);
+ cell.appendChild(button);
+ cell.setAttribute("class", "button");
+ });
+}
+
+function focusFilter() {
+ select("#filter").focus();
+}
+
+function resetFilter() {
+ var filter = select("#filter");
+ filter.focus();
+ if (filter.value.length > 0) {
+ filter.value = "";
+ reloadCookieTable();
+ }
+}
+
+var ESCAPE_KEY = 27;
+window.onkeydown = function(event) {
+ if (event.keyCode == ESCAPE_KEY) {
+ resetFilter();
+ }
+}
+
+function listener(info) {
+ cache.remove(info.cookie);
+ if (!info.removed) {
+ cache.add(info.cookie);
+ }
+ scheduleReloadCookieTable();
+}
+
+function startListening() {
+ chrome.cookies.onChanged.addListener(listener);
+}
+
+function stopListening() {
+ chrome.cookies.onChanged.removeListener(listener);
+}
+
+function onload() {
+ focusFilter();
+ var timer = new Timer();
+ chrome.cookies.getAll({}, function(cookies) {
+ startListening();
+ start = new Date();
+ for (var i in cookies) {
+ cache.add(cookies[i]);
+ }
+ timer.reset();
+ reloadCookieTable();
+ });
+}
+
+
+</script>
+</head>
+
+<body onload="onload()" onclick="focusFilter()">
+<h2>Cookies! ... Nom Nom Nom...</h2>
+<button onclick="removeAll()">DELETE ALL!</button>
+<div id="filter_div">
+Filter: <input id="filter" type="text" oninput="reloadCookieTable()">
+<button onclick="resetFilter()">x</button>
+</div>
+<br>
+<div id="summary_div">
+Showing <span id="filter_count"></span> of <span id="total_count"></span> cookie domains.
+<span id="delete_all_button"></span>
+</div>
+<br>
+<table id="cookies">
+<tr class="header">
+<th>Name</th>
+<th>#Cookies</th>
+</tr>
+</table>
+
+</body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/cookies/manifest.json b/chrome/common/extensions/docs/examples/api/cookies/manifest.json
new file mode 100644
index 0000000..3abe984
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/cookies/manifest.json
@@ -0,0 +1,11 @@
+{
+ "name" : "Cookie API Test Extension",
+ "version" : "0.7",
+ "description" : "Testing Cookie API",
+ "permissions": [ "cookies", "tabs", "http://*/*", "https://*/*" ],
+ "icons": { "16": "cookie.png", "48": "cookie.png", "128": "cookie.png" },
+ "browser_action": {
+ "default_icon": "cookie.png"
+ },
+ "background_page": "background.html"
+}
diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory.zip b/chrome/common/extensions/docs/examples/api/history/showHistory.zip
new file mode 100644
index 0000000..970cf68
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/history/showHistory.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory/clock.png b/chrome/common/extensions/docs/examples/api/history/showHistory/clock.png
new file mode 100644
index 0000000..08682cf
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/history/showHistory/clock.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory/manifest.json b/chrome/common/extensions/docs/examples/api/history/showHistory/manifest.json
new file mode 100644
index 0000000..2b271df
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/history/showHistory/manifest.json
@@ -0,0 +1,10 @@
+{
+ "name": "Typed URL History",
+ "version": "1.0",
+ "description": "Reads your history, and shows the top ten pages you go to by typing the URL.",
+ "permissions": ["history", "tabs"],
+ "browser_action": {
+ "default_popup": "typedUrls.html",
+ "default_icon": "clock.png"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.html b/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.html
new file mode 100644
index 0000000..26c86a3
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <title>Recently Typed URLs</title>
+ <style>
+ body {min-width: 250px;}
+ </style>
+ <script src='typedUrls.js'></script>
+ </head>
+
+ <body onload='buildTypedUrlList("typedUrl_div")' >
+ <h2>Recently Typed URLs:</h2>
+ <div id='typedUrl_div'></div>
+ </body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.js b/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.js
new file mode 100644
index 0000000..1b7f03b
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/history/showHistory/typedUrls.js
@@ -0,0 +1,113 @@
+// Event listner for clicks on links in a browser action popup.
+// Open the link in a new tab of the current window.
+function onAnchorClick(event) {
+ chrome.tabs.create({
+ selected: true,
+ url: event.srcElement.href
+ });
+ return false;
+}
+
+// Given an array of URLs, build a DOM list of those URLs in the
+// browser action popup.
+function buildPopupDom(divName, data) {
+ var popupDiv = document.getElementById(divName);
+
+ var ul = document.createElement('ul');
+ popupDiv.appendChild(ul);
+
+ for (var i = 0, ie = data.length; i < ie; ++i) {
+ var a = document.createElement('a');
+ a.href = data[i];
+ a.appendChild(document.createTextNode(data[i]));
+ a.addEventListener('click', onAnchorClick);
+
+ var li = document.createElement('li');
+ li.appendChild(a);
+
+ ul.appendChild(li);
+ }
+}
+
+// Search history to find up to ten links that a user has typed in,
+// and show those links in a popup.
+function buildTypedUrlList(divName) {
+ // To look for history items visited in the last week,
+ // subtract a week of microseconds from the current time.
+ var microsecondsPerWeek = 1000 * 60 * 60 * 24 * 7;
+ var oneWeekAgo = (new Date).getTime() - microsecondsPerWeek;
+
+ // Track the number of callbacks from chrome.history.getVisits()
+ // that we expect to get. When it reaches zero, we have all results.
+ var numRequestsOutstanding = 0;
+
+ chrome.history.search({
+ 'text': '', // Return every history item....
+ 'startTime': oneWeekAgo // that was accessed less than one week ago.
+ },
+ function(historyItems) {
+ // For each history item, get details on all visits.
+ for (var i = 0; i < historyItems.length; ++i) {
+ var url = historyItems[i].url;
+ var processVisitsWithUrl = function(url) {
+ // We need the url of the visited item to process the visit.
+ // Use a closure to bind the url into the callback's args.
+ return function(visitItems) {
+ processVisits(url, visitItems);
+ };
+ };
+ chrome.history.getVisits({url: url}, processVisitsWithUrl(url));
+ numRequestsOutstanding++;
+ }
+ if (!numRequestsOutstanding) {
+ onAllVisitsProcessed();
+ }
+ });
+
+
+ // Maps URLs to a count of the number of times the user typed that URL into
+ // the omnibox.
+ var urlToCount = {};
+
+ // Callback for chrome.history.getVisits(). Counts the number of
+ // times a user visited a URL by typing the address.
+ var processVisits = function(url, visitItems) {
+ for (var i = 0, ie = visitItems.length; i < ie; ++i) {
+ // Ignore items unless the user typed the URL.
+ if (visitItems[i].transition != 'typed') {
+ continue;
+ }
+
+ if (!urlToCount[url]) {
+ urlToCount[url] = 0;
+ }
+
+ urlToCount[url]++;
+ }
+
+ // If this is the final outstanding call to processVisits(),
+ // then we have the final results. Use them to build the list
+ // of URLs to show in the popup.
+ if (!--numRequestsOutstanding) {
+ onAllVisitsProcessed();
+ }
+ };
+
+ // This function is called when we have the final list of URls to display.
+ var onAllVisitsProcessed = function() {
+ // Get the top scorring urls.
+ urlArray = [];
+ for (var url in urlToCount) {
+ urlArray.push(url);
+ }
+
+ // Sort the URLs by the number of times the user typed them.
+ urlArray.sort(function(a, b) {
+ return urlToCount[b] - urlToCount[a];
+ });
+
+ buildPopupDom(divName, urlArray.slice(0, 10));
+ };
+}
+
+
diff --git a/chrome/common/extensions/docs/examples/api/i18n/cld.zip b/chrome/common/extensions/docs/examples/api/i18n/cld.zip
new file mode 100644
index 0000000..f809b4b
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/cld.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/i18n/cld/background.html b/chrome/common/extensions/docs/examples/api/i18n/cld/background.html
new file mode 100644
index 0000000..cfb1fac
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/cld/background.html
@@ -0,0 +1,32 @@
+<!--
+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.
+-->
+
+<script>
+var selectedId = -1;
+function refreshLanguage() {
+ chrome.tabs.detectLanguage(null, function(language) {
+ console.log(language);
+ if (language == " invalid_language_code")
+ language = "???";
+ chrome.browserAction.setBadgeText({"text": language, tabId: selectedId});
+ });
+}
+
+chrome.tabs.onUpdated.addListener(function(tabId, props) {
+ if (props.status == "complete" && tabId == selectedId)
+ refreshLanguage();
+});
+
+chrome.tabs.onSelectionChanged.addListener(function(tabId, props) {
+ selectedId = tabId;
+ refreshLanguage();
+});
+
+chrome.tabs.getSelected(null, function(tab) {
+ selectedId = tab.id;
+ refreshLanguage();
+});
+</script>
diff --git a/chrome/common/extensions/docs/examples/api/i18n/cld/manifest.json b/chrome/common/extensions/docs/examples/api/i18n/cld/manifest.json
new file mode 100644
index 0000000..f974838
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/cld/manifest.json
@@ -0,0 +1,12 @@
+{
+ "name": "CLD",
+ "description": "Displays the language of a tab",
+ "version": "0.1",
+ "background_page": "background.html",
+ "permissions": [
+ "tabs"
+ ],
+ "browser_action": {
+ "default_name": "Page Language"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage.zip b/chrome/common/extensions/docs/examples/api/i18n/getMessage.zip
new file mode 100644
index 0000000..a67a0ae
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/getMessage.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/en_US/messages.json b/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/en_US/messages.json
new file mode 100644
index 0000000..b33d2f0
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/en_US/messages.json
@@ -0,0 +1,27 @@
+{
+ "chrome_extension_name": {
+ "message": "AcceptLanguage"
+ },
+ "chrome_extension_description": {
+ "message": "Returns accept languages of the browser"
+ },
+ "click_here": {
+ "message": "Left click to list acceptLanguages."
+ },
+ "browser_action_title": {
+ "message": "Click Me"
+ },
+ "chrome_accept_languages": {
+ "message": "$CHROME$ accepts $languages$ languages",
+ "placeholders": {
+ "chrome": {
+ "content": "Chrome",
+ "example": "Chrome"
+ },
+ "languages": {
+ "content": "$1",
+ "example": "en-US,sr,de"
+ }
+ }
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/es/messages.json b/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/es/messages.json
new file mode 100644
index 0000000..c8267e4
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/es/messages.json
@@ -0,0 +1,27 @@
+{
+ "chrome_extension_name": {
+ "message": "AcceptLanguage"
+ },
+ "chrome_extension_description": {
+ "message": "Devuelve los idiomas aceptados por el navegador"
+ },
+ "click_here": {
+ "message": "Click con botón izquierdo para mostrar la lista de acceptLanguages."
+ },
+ "browser_action_title": {
+ "message": "Haz click aquí"
+ },
+ "chrome_accept_languages": {
+ "message": "$CHROME$ acepta los idiomas $languages$",
+ "placeholders": {
+ "chrome": {
+ "content": "Chrome",
+ "example": "Chrome"
+ },
+ "languages": {
+ "content": "$1",
+ "example": "en-US,sr,de"
+ }
+ }
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/sr/messages.json b/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/sr/messages.json
new file mode 100644
index 0000000..30bd958
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/getMessage/_locales/sr/messages.json
@@ -0,0 +1,24 @@
+{
+ "chrome_extension_name": {
+ "message": "Прихватљиви језици"
+ },
+ "chrome_extension_description": {
+ "message": "Језици које прегледач прихвата"
+ },
+ "click_here": {
+ "message": "Кликните да излиÑтате дозвољене језике."
+ },
+ "chrome_accept_languages": {
+ "message": "$CHROME$ прихвата $languages$ језике.",
+ "placeholders": {
+ "chrome": {
+ "content": "Chrome",
+ "example": "Chrome"
+ },
+ "languages": {
+ "content": "$1",
+ "example": "en-US,sr,de"
+ }
+ }
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/icon.png b/chrome/common/extensions/docs/examples/api/i18n/getMessage/icon.png
new file mode 100644
index 0000000..9a79a46
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/getMessage/icon.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/manifest.json b/chrome/common/extensions/docs/examples/api/i18n/getMessage/manifest.json
new file mode 100644
index 0000000..8b4e226
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/getMessage/manifest.json
@@ -0,0 +1,11 @@
+{
+ "name": "__MSG_chrome_extension_name__",
+ "description": "__MSG_chrome_extension_description__",
+ "version": "0.1",
+ "default_locale": "en_US",
+ "browser_action": {
+ "default_title": "__MSG_browser_action_title__",
+ "default_icon": "icon.png",
+ "popup": "popup.html"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.html b/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.html
new file mode 100644
index 0000000..f734779
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/i18n/getMessage/popup.html
@@ -0,0 +1,38 @@
+<!--
+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.
+-->
+
+<html>
+ <head>
+ <style>
+body {
+ color: black;
+ width: 300px;
+}
+ </style>
+ <script>
+ function setChildTextNode(elementId, text) {
+ document.getElementById(elementId).innerText = text;
+ }
+
+ function init() {
+ setChildTextNode('languageSpan', chrome.i18n.getMessage("click_here"));
+ }
+
+ function getAcceptLanguages() {
+ chrome.i18n.getAcceptLanguages(function(languageList) {
+ var languages = languageList.join(",");
+ setChildTextNode('languageSpan',
+ chrome.i18n.getMessage("chrome_accept_languages", languages));
+ })
+ }
+ </script>
+ </head>
+ <body onload="init()">
+ <div onclick="getAcceptLanguages();">
+ <span id="languageSpan"></span>
+ </div>
+ </body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple.zip b/chrome/common/extensions/docs/examples/api/idle/idle_simple.zip
new file mode 100644
index 0000000..ff33a9a
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/background.html b/chrome/common/extensions/docs/examples/api/idle/idle_simple/background.html
new file mode 100644
index 0000000..47f94ac
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/background.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+ * Copyright (c) 2010 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.
+-->
+<html>
+ <head>
+ </head>
+ <body>
+ <script>
+ var history_log = [];
+
+ /**
+ * Stores a state every time an "active" event is sent, up to 20 items.
+ */
+ chrome.idle.onStateChanged.addListener(function(newstate) {
+ var time = new Date();
+ if (history_log.length >= 20) {
+ history_log.pop();
+ }
+ history_log.unshift({'state':newstate, 'time':time});
+ });
+
+ /**
+ * Opens history.html when the browser action is clicked.
+ * Used window.open because I didn't want the tabs permission.
+ */
+ chrome.browserAction.onClicked.addListener(function() {
+ window.open('history.html', 'testwindow', 'width=700,height=600');
+ });
+ </script>
+ </body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.html b/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.html
new file mode 100644
index 0000000..34b1414
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/history.html
@@ -0,0 +1,118 @@
+<!DOCTYPE html>
+<!--
+ * Copyright (c) 2010 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.
+-->
+<html>
+ <head>
+ <style>
+ body {
+ width: 100%;
+ font: 13px Arial;
+ }
+ </style>
+ <script>
+ /**
+ * Convert a state and time into a nice styled chunk of HTML.
+ */
+ function renderState(state, time) {
+ var now = new Date().getTime();
+ var diff = Math.round((time.getTime() - now) / 1000);
+ var str = (diff == 0) ?
+ "now" :
+ Math.abs(diff) + " seconds " + (diff > 0 ? "from now" : "ago");
+ var col = (state == "active") ?
+ "#009900" :
+ "#990000";
+ return "<b style='color: " + col + "'>" + state + "</b> " + str;
+ };
+
+ /**
+ * Creates DOM and injects a rendered state into the page.
+ */
+ function renderItem(state, time, parent) {
+ var dom_item = document.createElement('li');
+ dom_item.innerHTML = renderState(state, time);
+ parent.appendChild(dom_item);
+ };
+ </script>
+ </head>
+ <body>
+ <h1>Idle API Demonstration</h1>
+ <h2>Current state</h2>
+ <p>
+ Idle threshold:
+ <select id="idle-threshold">
+ <option selected value="15">15</option>
+ <option value="30">30</option>
+ <option value="60">60</option>
+ </select>
+ <p>
+ <code>chrome.idle.queryState(<strong id="idle-set-threshold"></strong>, ...);</code> -
+ <span id="idle-state"></span>
+ </p>
+ <p>
+ Last state change: <span id="idle-laststate"></span>
+ </p>
+ <script>
+ // Store previous state so we can show deltas. This is important
+ // because the API currently doesn't fire idle messages, and we'd
+ // like to keep track of last time we went idle.
+ var laststate = null;
+ var laststatetime = null;
+
+ /**
+ * Checks the current state of the browser.
+ */
+ function checkState() {
+ threshold = parseInt(document.querySelector('#idle-threshold').value);
+ var dom_threshold = document.querySelector('#idle-set-threshold');
+ dom_threshold.innerText = threshold;
+
+ // Request the state based off of the user-supplied threshold.
+ chrome.idle.queryState(threshold, function(state) {
+ var time = new Date();
+ if (laststate != state) {
+ laststate = state;
+ laststatetime = time;
+ }
+
+ // Keep rendering results so we get a nice "seconds elapsed" view.
+ var dom_result = document.querySelector('#idle-state');
+ dom_result.innerHTML = renderState(state, time);
+ var dom_laststate = document.querySelector('#idle-laststate');
+ dom_laststate.innerHTML = renderState(laststate, laststatetime);
+ });
+ };
+
+ // Check every second (even though this is overkill - minimum idle
+ // threshold is 15 seconds) so that the numbers appear to be counting up.
+ checkState();
+ window.setInterval(checkState, 1000);
+ </script>
+
+ <h2>Idle changes:</h2>
+ <ul id='idle-history'></ul>
+ <script>
+ var dom_history = document.querySelector('#idle-history');
+
+ /**
+ * Render the data gathered by the background page - should show a log
+ * of "active" states. No events are fired upon idle.
+ */
+ function renderHistory() {
+ dom_history.innerHTML = "";
+ var history_log = chrome.extension.getBackgroundPage().history_log;
+ for (var i = 0; i < history_log.length; i++) {
+ var data = history_log[i];
+ renderItem(data['state'], data['time'], dom_history);
+ }
+ };
+
+ // Check every second (see above).
+ renderHistory();
+ window.setInterval(renderHistory, 1000);
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/manifest.json b/chrome/common/extensions/docs/examples/api/idle/idle_simple/manifest.json
new file mode 100644
index 0000000..9ec9902
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/manifest.json
@@ -0,0 +1,15 @@
+{
+ "name" : "Idle - Simple Example",
+ "version" : "1.0.0",
+ "description" : "Demonstrates the Idle API",
+ "background_page" : "background.html",
+ "permissions" : [ "idle" ],
+ "browser_action" : {
+ "default_icon" : "sample-19.png"
+ },
+ "icons" : {
+ "16" : "sample-16.png",
+ "48" : "sample-48.png",
+ "128" : "sample-128.png"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-128.png b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-128.png
new file mode 100644
index 0000000..1c961db
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-128.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-16.png b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-16.png
new file mode 100644
index 0000000..a10636f
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-16.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-19.png b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-19.png
new file mode 100644
index 0000000..32f265a
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-19.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-48.png b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-48.png
new file mode 100644
index 0000000..bee88b7
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-48.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar.zip b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar.zip
new file mode 100644
index 0000000..5a5c9f6
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/background.html b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/background.html
new file mode 100644
index 0000000..de48dde
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/background.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!--
+ * Copyright (c) 2010 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.
+-->
+<html>
+ <head>
+ </head>
+ <body>
+ <script>
+ /**
+ * Handles requests sent by the content script. Shows an infobar.
+ */
+ function onRequest(request, sender, sendResponse) {
+ // The number of matches is sent in the request - pass it to the
+ // infobar.
+ var url = "infobar.html#" + request.count;
+
+ // Show the infobar on the tab where the request was sent.
+ chrome.experimental.infobars.show({
+ tabId: sender.tab.id,
+ path: url
+ });
+
+ // Return nothing to let the connection be cleaned up.
+ sendResponse({});
+ };
+
+ // Listen for the content script to send a message to the background page.
+ chrome.extension.onRequest.addListener(onRequest);
+ </script>
+ </body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/contentscript.js b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/contentscript.js
new file mode 100644
index 0000000..6fa03ec
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/contentscript.js
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2010 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 regex = /sandwich/gi;
+matches = document.body.innerText.match(regex);
+if (matches) {
+ var payload = {
+ count: matches.length // Pass the number of matches back.
+ };
+ chrome.extension.sendRequest(payload, function(response) {});
+} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/infobar.html b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/infobar.html
new file mode 100644
index 0000000..3a765a5
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/infobar.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<!--
+ * Copyright (c) 2010 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.
+-->
+<html>
+ <head>
+ <style>
+ html {
+ height: 40px;
+ }
+ body {
+ background: #fffddd;
+ font: 16px Arial;
+ height: 100%;
+ display: -webkit-box;
+ -webkit-box-orient: vertical;
+ -webkit-box-pack: center;
+ }
+ em {
+ font-weight: bold;
+ font-style: normal;
+ }
+ </style>
+ </head>
+ <body>
+ <div id="wrap">
+ The word <em>sandwich</em> appears <em id="count">X</em> times on this
+ page.
+ </div>
+ <script>
+ // Obtain the count of sandwiches from the page URL.
+ var count = window.location.hash.substring(1);
+ if (count) {
+ // Replace the placeholder text with the actual count.
+ var domcount = document.querySelector('#count');
+ domcount.innerText = count;
+ }
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/manifest.json b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/manifest.json
new file mode 100644
index 0000000..89bdb51
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/manifest.json
@@ -0,0 +1,20 @@
+{
+ "name" : "SandwichBar",
+ "version" : "1.0.0",
+ "description" : "Shows an infobar on pages which contain the word 'sandwich'",
+ "background_page" : "background.html",
+ "permissions" : [ "experimental" ],
+ "icons" : {
+ "16" : "sandwich-16.png",
+ "48" : "sandwich-48.png",
+ "128" : "sandwich-128.png"
+ },
+ "content_scripts" : [
+ {
+ "matches" : [ "http://*/*" ],
+ "js" : [ "contentscript.js" ],
+ "run_at" : "document_idle",
+ "all_frames" : false
+ }
+ ]
+}
diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-128.png b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-128.png
new file mode 100644
index 0000000..a233154
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-128.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-16.png b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-16.png
new file mode 100644
index 0000000..86f3b3c
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-16.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-19.png b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-19.png
new file mode 100644
index 0000000..e84dc86
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-19.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-48.png b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-48.png
new file mode 100644
index 0000000..d7f2324
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-48.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer.zip b/chrome/common/extensions/docs/examples/api/messaging/timer.zip
new file mode 100644
index 0000000..8143322
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/messaging/timer.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/clock.png b/chrome/common/extensions/docs/examples/api/messaging/timer/clock.png
new file mode 100644
index 0000000..7889ac0
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/messaging/timer/clock.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/manifest.json b/chrome/common/extensions/docs/examples/api/messaging/timer/manifest.json
new file mode 100644
index 0000000..4717c41
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/messaging/timer/manifest.json
@@ -0,0 +1,17 @@
+{
+ "name": "Message Timer",
+ "version": "1.0",
+ "description": "Times how long it takes to send a message to a content script and back.",
+ "permissions": ["tabs"],
+ "content_scripts": [
+ {
+ "matches": ["http://*/*"],
+ "js": ["page.js"]
+ }
+ ],
+ "browser_action": {
+ "default_title": "Time to current page",
+ "default_icon": "clock.png",
+ "popup": "popup.html"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/page.js b/chrome/common/extensions/docs/examples/api/messaging/timer/page.js
new file mode 100644
index 0000000..92f8df3
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/messaging/timer/page.js
@@ -0,0 +1,10 @@
+chrome.extension.onConnect.addListener(function(port) {
+ port.onMessage.addListener(function(msg) {
+ port.postMessage({counter: msg.counter+1});
+ });
+});
+
+chrome.extension.onRequest.addListener(
+ function(request, sender, sendResponse) {
+ sendResponse({counter: request.counter+1});
+ });
diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/popup.html b/chrome/common/extensions/docs/examples/api/messaging/timer/popup.html
new file mode 100644
index 0000000..e20e799
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/messaging/timer/popup.html
@@ -0,0 +1,77 @@
+<head>
+<style>
+tr {
+ white-space: nowrap;
+}
+.results {
+ text-align: right;
+ min-width: 6em;
+ color: black;
+}
+</style>
+<script>
+if (!chrome.benchmarking) {
+ alert("Warning: Looks like you forgot to run chrome with " +
+ " --enable-benchmarking set.");
+ return;
+}
+
+function setChildTextNode(elementId, text) {
+ document.getElementById(elementId).innerText = text;
+}
+
+// Tests the roundtrip time of sendRequest().
+function testRequest() {
+ setChildTextNode("resultsRequest", "running...");
+
+ chrome.tabs.getSelected(null, function(tab) {
+ var timer = new chrome.Interval();
+ timer.start();
+
+ chrome.tabs.sendRequest(tab.id, {counter: 1}, function handler(response) {
+ if (response.counter < 1000) {
+ chrome.tabs.sendRequest(tab.id, {counter: response.counter}, handler);
+ } else {
+ timer.stop();
+ var usec = Math.round(timer.microseconds() / response.counter);
+ setChildTextNode("resultsRequest", usec + "usec");
+ }
+ });
+ });
+}
+
+// Tests the roundtrip time of Port.postMessage() after opening a channel.
+function testConnect() {
+ setChildTextNode("resultsConnect", "running...");
+
+ chrome.tabs.getSelected(null, function(tab) {
+ var timer = new chrome.Interval();
+ timer.start();
+
+ var port = chrome.tabs.connect(tab.id);
+ port.postMessage({counter: 1});
+ port.onMessage.addListener(function getResp(response) {
+ if (response.counter < 1000) {
+ port.postMessage({counter: response.counter});
+ } else {
+ timer.stop();
+ var usec = Math.round(timer.microseconds() / response.counter);
+ setChildTextNode("resultsConnect", usec + "usec");
+ }
+ });
+ });
+}
+</script>
+</head>
+<body>
+<table>
+ <tr>
+ <td><button onclick="testRequest()">Measure sendRequest</button></td>
+ <td id="resultsRequest" class="results">(results)</td>
+ </tr>
+ <tr>
+ <td><button onclick="testConnect()">Measure postMessage</button></td>
+ <td id="resultsConnect" class="results">(results)</td>
+ </tr>
+</table>
+</body>
diff --git a/chrome/common/extensions/docs/examples/api/notifications.zip b/chrome/common/extensions/docs/examples/api/notifications.zip
new file mode 100644
index 0000000..2013295
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/notifications.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/notifications/128.png b/chrome/common/extensions/docs/examples/api/notifications/128.png
new file mode 100644
index 0000000..7013aa9
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/notifications/128.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/notifications/16.png b/chrome/common/extensions/docs/examples/api/notifications/16.png
new file mode 100644
index 0000000..669c791
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/notifications/16.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/notifications/48.png b/chrome/common/extensions/docs/examples/api/notifications/48.png
new file mode 100644
index 0000000..8a151ad
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/notifications/48.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/notifications/64.png b/chrome/common/extensions/docs/examples/api/notifications/64.png
new file mode 100644
index 0000000..347e28f
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/notifications/64.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/notifications/background.html b/chrome/common/extensions/docs/examples/api/notifications/background.html
new file mode 100644
index 0000000..0d192fa
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/notifications/background.html
@@ -0,0 +1,58 @@
+<!--
+ A background page that manages notifications.
+
+ Copyright 2010 the Chromium Authors
+
+ Use of this source code is governed by a BSD-style license that can be found
+ in the "LICENSE" file.
+
+ Brian Kennish <bkennish@chromium.org>
+-->
+<script>
+ /*
+ Displays a notification with the current time. Requires "notifications"
+ permission in the manifest file (or calling
+ "webkitNotifications.requestPermission" beforehand).
+ */
+ function show() {
+ var time = /(..)(:..)/(Date()); // The prettyprinted time.
+ var hour = time[1] % 12 || 12; // The prettyprinted hour.
+ var period = time[1] < 12 ? 'a.m.' : 'p.m.'; // The period of the day.
+ var notification = webkitNotifications.createNotification(
+ '48.png', // The image.
+ hour + time[2] + ' ' + period, // The title.
+ 'Time to make the toast.' // The body.
+ );
+ notification.show();
+ }
+
+ // Conditionally initialize the options.
+ if (!localStorage.isInitialized) {
+ localStorage.isActivated = true; // The display activation.
+ localStorage.frequency = 1; // The display frequency, in minutes.
+ localStorage.isInitialized = true; // The option initialization.
+ }
+
+ // Test for notification support.
+ if (webkitNotifications) {
+ // While activated, show notifications at the display frequency.
+ if (JSON.parse(localStorage.isActivated)) { show(); }
+
+ var interval = 0; // The display interval, in minutes.
+
+ setInterval(function() {
+ interval++;
+
+ if (
+ JSON.parse(localStorage.isActivated) &&
+ localStorage.frequency <= interval
+ ) {
+ show();
+ interval = 0;
+ }
+ }, 60000);
+ } else {
+ // Show a new tab with an error message.
+ chrome.tabs.create({url: 'error.html'});
+ }
+</script>
diff --git a/chrome/common/extensions/docs/examples/api/notifications/error.html b/chrome/common/extensions/docs/examples/api/notifications/error.html
new file mode 100644
index 0000000..1a20c42
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/notifications/error.html
@@ -0,0 +1,41 @@
+<!--
+ An error page for browsers that don't implement notifications.
+
+ Copyright 2010 the Chromium Authors
+
+ Use of this source code is governed by a BSD-style license that can be found
+ in the "LICENSE" file.
+
+ Brian Kennish <bkennish@chromium.org>
+-->
+<title>Notification Demo</title>
+<style>
+ /* Clone the look and feel of "chrome://" pages. */
+ body {
+ margin: 10px;
+ font: 84% Arial, sans-serif
+ }
+
+ h1 { font-size: 156% }
+
+ h1 img {
+ margin: 1px 5px 0 1px;
+ vertical-align: middle
+ }
+
+ h2 {
+ border-top: 1px solid #9cc2ef;
+ background-color: #ebeff9;
+ padding: 3px 5px;
+ font-size: 100%
+ }
+</style>
+<h1>
+ <img src="64.png" alt="Toast">
+ Notification Demo
+</h1>
+<h2>Error</h2>
+<p>
+ Desktop notifications are supported only by Google Chrome 4 and up on Windows
+ and Google Chrome 5 and up on the Mac and Linux.
+</p>
diff --git a/chrome/common/extensions/docs/examples/api/notifications/manifest.json b/chrome/common/extensions/docs/examples/api/notifications/manifest.json
new file mode 100644
index 0000000..dfc0d15
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/notifications/manifest.json
@@ -0,0 +1,10 @@
+{
+ "name": "Notification Demo",
+ "version": "1",
+ "description":
+ "Shows off desktop notifications, which are \"toast\" windows that pop up on the desktop.",
+ "icons": {"16": "16.png", "48": "48.png", "128": "128.png"},
+ "permissions": ["tabs", "notifications"],
+ "options_page": "options.html",
+ "background_page": "background.html"
+}
diff --git a/chrome/common/extensions/docs/examples/api/notifications/options.html b/chrome/common/extensions/docs/examples/api/notifications/options.html
new file mode 100644
index 0000000..a06df0c
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/notifications/options.html
@@ -0,0 +1,85 @@
+<!--
+ An option page for configuring notifications.
+
+ Copyright 2010 the Chromium Authors
+
+ Use of this source code is governed by a BSD-style license that can be found
+ in the "LICENSE" file.
+
+ Brian Kennish <bkennish@chromium.org>
+-->
+<title>Notification Demo</title>
+<style>
+ /* Clone the look and feel of "chrome://" pages. */
+ body {
+ margin: 10px;
+ font: 84% Arial, sans-serif
+ }
+
+ h1 { font-size: 156% }
+
+ h1 img {
+ margin: 1px 5px 0 1px;
+ vertical-align: middle
+ }
+
+ h2 {
+ border-top: 1px solid #9cc2ef;
+ background-color: #ebeff9;
+ padding: 3px 5px;
+ font-size: 100%
+ }
+</style>
+<script>
+ /*
+ Grays out or [whatever the opposite of graying out is called] the option
+ field.
+ */
+ function ghost(isDeactivated) {
+ options.style.color = isDeactivated ? 'graytext' : 'black';
+ // The label color.
+ options.frequency.disabled = isDeactivated; // The control manipulability.
+ }
+
+ onload = function() {
+ // Initialize the option controls.
+ options.isActivated.checked = JSON.parse(localStorage.isActivated);
+ // The display activation.
+ options.frequency.value = localStorage.frequency;
+ // The display frequency, in minutes.
+
+ if (!options.isActivated.checked) { ghost(true); }
+
+ // Set the display activation and frequency.
+ options.isActivated.onchange = function() {
+ localStorage.isActivated = options.isActivated.checked;
+ ghost(!options.isActivated.checked);
+ };
+
+ options.frequency.onchange = function() {
+ localStorage.frequency = options.frequency.value;
+ };
+ };
+</script>
+<h1>
+ <img src="64.png" alt="Toast">
+ Notification Demo
+</h1>
+<h2>Options</h2>
+<form id="options">
+ <input type="checkbox" name="isActivated" checked>
+ Display a notification every
+ <select name="frequency">
+ <option>1</option>
+ <option>2</option>
+ <option>3</option>
+ <option>4</option>
+ <option>5</option>
+ <option>10</option>
+ <option>15</option>
+ <option>20</option>
+ <option>25</option>
+ <option>30</option>
+ </select>
+ minute(s).
+</form>
diff --git a/chrome/common/extensions/docs/examples/api/omnibox.zip b/chrome/common/extensions/docs/examples/api/omnibox.zip
new file mode 100644
index 0000000..fdebe41
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/omnibox.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/background.html b/chrome/common/extensions/docs/examples/api/omnibox/background.html
new file mode 100644
index 0000000..ff83ff2
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/omnibox/background.html
@@ -0,0 +1,19 @@
+<script>
+// This event is fired each time the user updates the text in the omnibox,
+// as long as the extension's keyword mode is still active.
+chrome.experimental.omnibox.onInputChanged.addListener(
+ function(text, suggest) {
+ console.log('inputChanged: ' + text);
+ suggest([
+ {content: text + " one", description: "the first one"},
+ {content: text + " number two", description: "the second entry"}
+ ]);
+ });
+
+// This event is fired with the user accepts the input in the omnibox.
+chrome.experimental.omnibox.onInputEntered.addListener(
+ function(text) {
+ console.log('inputEntered: ' + text);
+ alert('You just typed "' + text + '"');
+ });
+</script>
diff --git a/chrome/common/extensions/docs/examples/api/omnibox/manifest.json b/chrome/common/extensions/docs/examples/api/omnibox/manifest.json
new file mode 100644
index 0000000..2b63ca2
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/omnibox/manifest.json
@@ -0,0 +1,7 @@
+{
+ "name": "Omnibox Example",
+ "version": "1.0",
+ "permissions": [ "experimental" ],
+ "background_page": "background.html",
+ "omnibox_keyword": "omnix"
+}
diff --git a/chrome/common/extensions/docs/examples/api/override/blank_ntp.zip b/chrome/common/extensions/docs/examples/api/override/blank_ntp.zip
new file mode 100644
index 0000000..ea5f6c7
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/override/blank_ntp.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/override/blank_ntp/blank.html b/chrome/common/extensions/docs/examples/api/override/blank_ntp/blank.html
new file mode 100644
index 0000000..87cf3ed
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/override/blank_ntp/blank.html
@@ -0,0 +1,19 @@
+<html>
+ <head>
+ <title>Blank New Tab</title>
+ <style>
+ div {
+ color: #cccccc;
+ vertical-align: 50%;
+ text-align: center;
+ font-family: sans-serif;
+ font-size: 300%;
+ }
+ </style>
+ </head>
+ <body>
+ <div style="height:40%"></div>
+ <div>Blank New Tab&trade;</div>
+ </body>
+</html>
+
diff --git a/chrome/common/extensions/docs/examples/api/override/blank_ntp/manifest.json b/chrome/common/extensions/docs/examples/api/override/blank_ntp/manifest.json
new file mode 100644
index 0000000..671075e
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/override/blank_ntp/manifest.json
@@ -0,0 +1,8 @@
+{
+ "name": "Blank new tab page",
+ "version": "0.1",
+ "incognito": "split",
+ "chrome_url_overrides": {
+ "newtab": "blank.html"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/override/override_igoogle.zip b/chrome/common/extensions/docs/examples/api/override/override_igoogle.zip
new file mode 100644
index 0000000..bdd90fd
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/override/override_igoogle.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/override/override_igoogle/manifest.json b/chrome/common/extensions/docs/examples/api/override/override_igoogle/manifest.json
new file mode 100644
index 0000000..461da24
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/override/override_igoogle/manifest.json
@@ -0,0 +1,7 @@
+{
+ "name": "iGoogle new tab page",
+ "version": "0.1",
+ "chrome_url_overrides": {
+ "newtab": "redirect.html"
+ }
+} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/override/override_igoogle/redirect.html b/chrome/common/extensions/docs/examples/api/override/override_igoogle/redirect.html
new file mode 100644
index 0000000..35117f4
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/override/override_igoogle/redirect.html
@@ -0,0 +1,3 @@
+<head>
+<meta http-equiv="refresh"content="0;URL=http://www.google.com/ig">
+</head>
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content.zip b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content.zip
new file mode 100644
index 0000000..714f749
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/background.html b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/background.html
new file mode 100644
index 0000000..2c545fd
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/background.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!--
+ * Copyright (c) 2010 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.
+-->
+<html>
+ <head>
+ <script>
+ // Called when a message is passed. We assume that the content script
+ // wants to show the page action.
+ function onRequest(request, sender, sendResponse) {
+ // Show the page action for the tab that the sender (content script)
+ // was on.
+ chrome.pageAction.show(sender.tab.id);
+
+ // Return nothing to let the connection be cleaned up.
+ sendResponse({});
+ };
+
+ // Listen for the content script to send a message to the background page.
+ chrome.extension.onRequest.addListener(onRequest);
+ </script>
+ </head>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/contentscript.js b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/contentscript.js
new file mode 100644
index 0000000..91037bb
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/contentscript.js
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2010 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 regex = /sandwich/;
+
+// Test the text of the body element against our regular expression.
+if (regex.test(document.body.innerText)) {
+ // The regular expression produced a match, so notify the background page.
+ chrome.extension.sendRequest({}, function(response) {});
+} else {
+ // No match was found.
+}
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/manifest.json b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/manifest.json
new file mode 100644
index 0000000..50643ee
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/manifest.json
@@ -0,0 +1,26 @@
+{
+ "name" : "Page action by content",
+ "version" : "1.0",
+ "description" : "Shows a page action for HTML pages containing the word 'sandwich'",
+ "background_page" : "background.html",
+ "page_action" :
+ {
+ "default_icon" : "sandwich-19.png",
+ "default_title" : "There's a 'sandwich' in this page!"
+ },
+ "content_scripts" : [
+ {
+ "matches" : [
+ "http://*/*",
+ "https://*/*"
+ ],
+ "js" : ["contentscript.js"],
+ "run_at" : "document_idle",
+ "all_frames" : false
+ }
+ ],
+ "icons" : {
+ "48" : "sandwich-48.png",
+ "128" : "sandwich-128.png"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-128.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-128.png
new file mode 100644
index 0000000..a233154
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-128.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-19.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-19.png
new file mode 100644
index 0000000..e84dc86
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-19.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-48.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-48.png
new file mode 100644
index 0000000..d7f2324
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-48.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url.zip b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url.zip
new file mode 100644
index 0000000..25365b6
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/background.html b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/background.html
new file mode 100644
index 0000000..d30ace2
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/background.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!--
+ * Copyright (c) 2010 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.
+-->
+<html>
+ <head>
+ <script>
+ // Called when the url of a tab changes.
+ function checkForValidUrl(tabId, changeInfo, tab) {
+ // If the letter 'g' is found in the tab's URL...
+ if (tab.url.indexOf('g') > -1) {
+ // ... show the page action.
+ chrome.pageAction.show(tabId);
+ }
+ };
+
+ // Listen for any changes to the URL of any tab.
+ chrome.tabs.onUpdated.addListener(checkForValidUrl);
+ </script>
+ </head>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-128.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-128.png
new file mode 100644
index 0000000..fbfe538
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-128.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-19.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-19.png
new file mode 100644
index 0000000..91679f0
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-19.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-48.png b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-48.png
new file mode 100644
index 0000000..59e9935
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-48.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/manifest.json b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/manifest.json
new file mode 100644
index 0000000..ce991fa
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/manifest.json
@@ -0,0 +1,18 @@
+{
+ "name": "Page action by URL",
+ "version": "1.0",
+ "description": "Shows a page action for urls which have the letter 'g' in them.",
+ "background_page": "background.html",
+ "page_action" :
+ {
+ "default_icon" : "icon-19.png",
+ "default_title" : "There's a 'G' in this URL!"
+ },
+ "permissions" : [
+ "tabs"
+ ],
+ "icons" : {
+ "48" : "icon-48.png",
+ "128" : "icon-128.png"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon.zip b/chrome/common/extensions/docs/examples/api/pageAction/set_icon.zip
new file mode 100644
index 0000000..9bd5927
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/set_icon.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.html b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.html
new file mode 100644
index 0000000..9986850
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/background.html
@@ -0,0 +1,69 @@
+<html>
+<head>
+<script>
+ var lastTabId = 0;
+ var tab_clicks = {};
+
+ chrome.tabs.onSelectionChanged.addListener(function(tabId) {
+ lastTabId = tabId;
+ chrome.pageAction.show(lastTabId);
+ });
+
+ chrome.tabs.getSelected(null, function(tab) {
+ lastTabId = tab.id;
+ chrome.pageAction.show(lastTabId);
+ });
+
+ // Called when the user clicks on the page action.
+ chrome.pageAction.onClicked.addListener(function(tab) {
+ var clicks = tab_clicks[tab.id] || 0;
+ chrome.pageAction.setIcon({path: "icon" + (clicks + 1) + ".png",
+ tabId: tab.id});
+ if (clicks % 2) {
+ chrome.pageAction.show(tab.id);
+ } else {
+ chrome.pageAction.hide(tab.id);
+ setTimeout(function() { chrome.pageAction.show(tab.id); }, 200);
+ }
+ chrome.pageAction.setTitle({title: "click:" + clicks, tabId: tab.id});
+
+ // We only have 2 icons, but cycle through 3 icons to test the
+ // out-of-bounds index bug.
+ clicks++;
+ if (clicks > 3)
+ clicks = 0;
+ tab_clicks[tab.id] = clicks;
+ });
+
+ var i = 0;
+ window.setInterval(function() {
+ var clicks = tab_clicks[lastTabId] || 0;
+
+ // Don't animate while in "click" mode.
+ if (clicks > 0) return;
+
+ // Don't do anything if we don't have a tab yet.
+ if (lastTabId == 0) return;
+
+ i++;
+ chrome.pageAction.setIcon({imageData: draw(i*2, i*4), tabId: lastTabId});
+ }, 50);
+
+ function draw(starty, startx) {
+ var canvas = document.getElementById('canvas');
+ var context = canvas.getContext('2d');
+ context.clearRect(0, 0, canvas.width, canvas.height);
+ context.fillStyle = "rgba(0,200,0,255)";
+ context.fillRect(startx % 19, starty % 19, 8, 8);
+ context.fillStyle = "rgba(0,0,200,255)";
+ context.fillRect((startx + 5) % 19, (starty + 5) % 19, 8, 8);
+ context.fillStyle = "rgba(200,0,0,255)";
+ context.fillRect((startx + 10) % 19, (starty + 10) % 19, 8, 8);
+ return context.getImageData(0, 0, 19, 19);
+ }
+</script>
+</head>
+<body>
+<canvas id="canvas" width="19" height="19"></canvas>
+</body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon1.png b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon1.png
new file mode 100644
index 0000000..9a79a46
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon1.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon2.png b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon2.png
new file mode 100644
index 0000000..8d3f710
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon2.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/pageAction/set_icon/manifest.json b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/manifest.json
new file mode 100644
index 0000000..5a374e8
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/manifest.json
@@ -0,0 +1,10 @@
+{
+ "name": "Animated Page Action",
+ "description": "This extension adds an animated browser action to the toolbar.",
+ "version": "1.0",
+ "permissions": ["tabs"],
+ "background_page": "background.html",
+ "page_action": {
+ "default_title": "First icon"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs.zip b/chrome/common/extensions/docs/examples/api/processes/show_tabs.zip
new file mode 100644
index 0000000..08659d1
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/processes/show_tabs.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs/icon.png b/chrome/common/extensions/docs/examples/api/processes/show_tabs/icon.png
new file mode 100644
index 0000000..9a79a46
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/processes/show_tabs/icon.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs/manifest.json b/chrome/common/extensions/docs/examples/api/processes/show_tabs/manifest.json
new file mode 100644
index 0000000..c1711eb
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/processes/show_tabs/manifest.json
@@ -0,0 +1,13 @@
+{
+ "name": "Show Tabs in Process",
+ "version": "1.0",
+ "description": "Adds a browser action showing which tabs share the current tab's process.",
+ "permissions": [
+ "experimental", "tabs"
+ ],
+ "browser_action": {
+ "default_title": "Show Tabs in this Process",
+ "default_icon": "icon.png",
+ "popup": "popup.html"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.html b/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.html
new file mode 100644
index 0000000..8f69fc0
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/processes/show_tabs/popup.html
@@ -0,0 +1,92 @@
+<html>
+<head>
+<script>
+ // Show a list of all tabs in the same process as this one.
+ function init() {
+ chrome.windows.getCurrent(function(currentWindow) {
+ chrome.tabs.getSelected(currentWindow.id, function(selectedTab) {
+ chrome.experimental.processes.getProcessForTab(selectedTab.id,
+ function(process) {
+ var outputDiv = document.getElementById("tab-list");
+ var titleDiv = document.getElementById("title");
+ titleDiv.innerHTML = "<b>Tabs in Process " + process.id + ":</b>";
+ displayTabInfo(currentWindow.id, selectedTab, outputDiv);
+ displaySameProcessTabs(selectedTab, process.id, outputDiv);
+ }
+ );
+
+ });
+ });
+ }
+
+ function displaySameProcessTabs(selectedTab, processId, outputDiv) {
+ // Loop over all windows and their tabs
+ var tabs = [];
+ chrome.windows.getAll({ populate: true }, function(windowList) {
+ for (var i = 0; i < windowList.length; i++) {
+ for (var j = 0; j < windowList[i].tabs.length; j++) {
+ var tab = windowList[i].tabs[j];
+ if (tab.id != selectedTab.id) {
+ tabs.push(tab);
+ }
+ }
+ }
+
+ // Display tab in list if it is in the same process
+ tabs.forEach(function(tab) {
+ chrome.experimental.processes.getProcessForTab(tab.id,
+ function(process) {
+ if (process.id == processId) {
+ displayTabInfo(tab.windowId, tab, outputDiv);
+ }
+ }
+ );
+ });
+ });
+ }
+
+ // Print a link to a given tab
+ function displayTabInfo(windowId, tab, outputDiv) {
+ if (tab.favIconUrl != undefined) {
+ outputDiv.innerHTML += "<img src='" + tab.favIconUrl + "'>\n";
+ }
+ outputDiv.innerHTML +=
+ "<b><a href='#' onclick='showTab(window, " + windowId + ", " + tab.id +
+ ")'>" + tab.title + "</a></b><br>\n" +
+ "<i>" + tab.url + "</i><br>\n";
+ }
+
+ // Bring the selected tab to the front
+ function showTab(origWindow, windowId, tabId) {
+ // TODO: Bring the window to the front. (See http://crbug.com/31434)
+ //chrome.windows.update(windowId, {focused: true});
+ chrome.tabs.update(tabId, { selected: true });
+ origWindow.close();
+ }
+</script>
+<style>
+body {
+ overflow: hidden;
+ margin: 0px;
+ padding: 0px;
+ background: white;
+}
+
+div:first-child {
+ margin-top: 0px;
+}
+
+div {
+ padding: 1px 3px;
+ font-family: sans-serif;
+ font-size: 10pt;
+ width: 400px;
+ margin-top: 1px;
+}
+</style>
+</head>
+<body onload="init()" style="width: 400px">
+<div id="title"></div>
+<div id="tab-list"></div>
+</body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector.zip b/chrome/common/extensions/docs/examples/api/tabs/inspector.zip
new file mode 100644
index 0000000..36a74ad
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/inspector.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector/background.html b/chrome/common/extensions/docs/examples/api/tabs/inspector/background.html
new file mode 100644
index 0000000..314dc3c
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/inspector/background.html
@@ -0,0 +1,5 @@
+<script>
+chrome.browserAction.onClicked.addListener(function(tab) {
+ chrome.tabs.create({url:chrome.extension.getURL("tabs_api.html")});
+});
+</script> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector/jstemplate_compiled.js b/chrome/common/extensions/docs/examples/api/tabs/inspector/jstemplate_compiled.js
new file mode 100644
index 0000000..2f62b31
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/inspector/jstemplate_compiled.js
@@ -0,0 +1,1182 @@
+/**
+ * @fileoverview This file contains miscellaneous basic functionality.
+ *
+ */
+
+/**
+ * Creates a DOM element with the given tag name in the document of the
+ * owner element.
+ *
+ * @param {String} tagName The name of the tag to create.
+ * @param {Element} owner The intended owner (i.e., parent element) of
+ * the created element.
+ * @param {Point} opt_position The top-left corner of the created element.
+ * @param {Size} opt_size The size of the created element.
+ * @param {Boolean} opt_noAppend Do not append the new element to the owner.
+ * @return {Element} The newly created element node.
+ */
+function createElement(tagName, owner, opt_position, opt_size, opt_noAppend) {
+ var element = ownerDocument(owner).createElement(tagName);
+ if (opt_position) {
+ setPosition(element, opt_position);
+ }
+ if (opt_size) {
+ setSize(element, opt_size);
+ }
+ if (owner && !opt_noAppend) {
+ appendChild(owner, element);
+ }
+
+ return element;
+}
+
+/**
+ * Creates a text node with the given value.
+ *
+ * @param {String} value The text to place in the new node.
+ * @param {Element} owner The owner (i.e., parent element) of the new
+ * text node.
+ * @return {Text} The newly created text node.
+ */
+function createTextNode(value, owner) {
+ var element = ownerDocument(owner).createTextNode(value);
+ if (owner) {
+ appendChild(owner, element);
+ }
+ return element;
+}
+
+/**
+ * Returns the document owner of the given element. In particular,
+ * returns window.document if node is null or the browser does not
+ * support ownerDocument.
+ *
+ * @param {Node} node The node whose ownerDocument is required.
+ * @returns {Document|Null} The owner document or null if unsupported.
+ */
+function ownerDocument(node) {
+ return (node ? node.ownerDocument : null) || document;
+}
+
+/**
+ * Wrapper function to create CSS units (pixels) string
+ *
+ * @param {Number} numPixels Number of pixels, may be floating point.
+ * @returns {String} Corresponding CSS units string.
+ */
+function px(numPixels) {
+ return round(numPixels) + "px";
+}
+
+/**
+ * Sets the left and top of the given element to the given point.
+ *
+ * @param {Element} element The dom element to manipulate.
+ * @param {Point} point The desired position.
+ */
+function setPosition(element, point) {
+ var style = element.style;
+ style.position = "absolute";
+ style.left = px(point.x);
+ style.top = px(point.y);
+}
+
+/**
+ * Sets the width and height style attributes to the given size.
+ *
+ * @param {Element} element The dom element to manipulate.
+ * @param {Size} size The desired size.
+ */
+function setSize(element, size) {
+ var style = element.style;
+ style.width = px(size.width);
+ style.height = px(size.height);
+}
+
+/**
+ * Sets display to none. Doing this as a function saves a few bytes for
+ * the 'style.display' property and the 'none' literal.
+ *
+ * @param {Element} node The dom element to manipulate.
+ */
+function displayNone(node) {
+ node.style.display = 'none';
+}
+
+/**
+ * Sets display to default.
+ *
+ * @param {Element} node The dom element to manipulate.
+ */
+function displayDefault(node) {
+ node.style.display = '';
+}
+
+/**
+ * Appends the given child to the given parent in the DOM
+ *
+ * @param {Element} parent The parent dom element.
+ * @param {Node} child The new child dom node.
+ */
+function appendChild(parent, child) {
+ parent.appendChild(child);
+}
+
+
+/**
+ * Wrapper for the eval() builtin function to evaluate expressions and
+ * obtain their value. It wraps the expression in parentheses such
+ * that object literals are really evaluated to objects. Without the
+ * wrapping, they are evaluated as block, and create syntax
+ * errors. Also protects against other syntax errors in the eval()ed
+ * code and returns null if the eval throws an exception.
+ *
+ * @param {String} expr
+ * @return {Object|Null}
+ */
+function jsEval(expr) {
+ try {
+ return eval('[' + expr + '][0]');
+ } catch (e) {
+ return null;
+ }
+}
+
+
+/**
+ * Wrapper for the eval() builtin function to execute statements. This
+ * guards against exceptions thrown, but doesn't return a
+ * value. Still, mostly for testability, it returns a boolean to
+ * indicate whether execution was successful. NOTE:
+ * javascript's eval semantics is murky in that it confounds
+ * expression evaluation and statement execution into a single
+ * construct. Cf. jsEval().
+ *
+ * @param {String} stmt
+ * @return {Boolean}
+ */
+function jsExec(stmt) {
+ try {
+ eval(stmt);
+ return true;
+ } catch (e) {
+ return false;
+ }
+}
+
+
+/**
+ * Wrapper for eval with a context. NOTE: The style guide
+ * deprecates eval, so this is the exception that proves the
+ * rule. Notice also that since the value of the expression is
+ * returned rather than assigned to a local variable, one major
+ * objection aganist the use of the with() statement, namely that
+ * properties of the with() target override local variables of the
+ * same name, is void here.
+ *
+ * @param {String} expr
+ * @param {Object} context
+ * @return {Object|Null}
+ */
+function jsEvalWith(expr, context) {
+ try {
+ with (context) {
+ return eval('[' + expr + '][0]');
+ }
+ } catch (e) {
+ return null;
+ }
+}
+
+
+var DOM_ELEMENT_NODE = 1;
+var DOM_ATTRIBUTE_NODE = 2;
+var DOM_TEXT_NODE = 3;
+var DOM_CDATA_SECTION_NODE = 4;
+var DOM_ENTITY_REFERENCE_NODE = 5;
+var DOM_ENTITY_NODE = 6;
+var DOM_PROCESSING_INSTRUCTION_NODE = 7;
+var DOM_COMMENT_NODE = 8;
+var DOM_DOCUMENT_NODE = 9;
+var DOM_DOCUMENT_TYPE_NODE = 10;
+var DOM_DOCUMENT_FRAGMENT_NODE = 11;
+var DOM_NOTATION_NODE = 12;
+
+/**
+ * Traverses the element nodes in the DOM tree underneath the given
+ * node and finds the first node with elemId, or null if there is no such
+ * element. Traversal is in depth-first order.
+ *
+ * NOTE: The reason this is not combined with the elem() function is
+ * that the implementations are different.
+ * elem() is a wrapper for the built-in document.getElementById() function,
+ * whereas this function performs the traversal itself.
+ * Modifying elem() to take an optional root node is a possibility,
+ * but the in-built function would perform better than using our own traversal.
+ *
+ * @param {Element} node Root element of subtree to traverse.
+ * @param {String} elemId The id of the element to search for.
+ * @return {Element|Null} The corresponding element, or null if not found.
+ */
+function nodeGetElementById(node, elemId) {
+ for (var c = node.firstChild; c; c = c.nextSibling) {
+ if (c.id == elemId) {
+ return c;
+ }
+ if (c.nodeType == DOM_ELEMENT_NODE) {
+ var n = arguments.callee.call(this, c, elemId);
+ if (n) {
+ return n;
+ }
+ }
+ }
+ return null;
+}
+
+
+/**
+ * Get an attribute from the DOM. Simple redirect, exists to compress code.
+ *
+ * @param {Element} node Element to interrogate.
+ * @param {String} name Name of parameter to extract.
+ * @return {String} Resulting attribute.
+ */
+function domGetAttribute(node, name) {
+ return node.getAttribute(name);
+}
+
+/**
+ * Set an attribute in the DOM. Simple redirect to compress code.
+ *
+ * @param {Element} node Element to interrogate.
+ * @param {String} name Name of parameter to set.
+ * @param {String} value Set attribute to this value.
+ */
+function domSetAttribute(node, name, value) {
+ node.setAttribute(name, value);
+}
+
+/**
+ * Remove an attribute from the DOM. Simple redirect to compress code.
+ *
+ * @param {Element} node Element to interrogate.
+ * @param {String} name Name of parameter to remove.
+ */
+function domRemoveAttribute(node, name) {
+ node.removeAttribute(name);
+}
+
+/**
+ * Clone a node in the DOM.
+ *
+ * @param {Node} node Node to clone.
+ * @return {Node} Cloned node.
+ */
+function domCloneNode(node) {
+ return node.cloneNode(true);
+}
+
+
+/**
+ * Return a safe string for the className of a node.
+ * If className is not a string, returns "".
+ *
+ * @param {Element} node DOM element to query.
+ * @return {String}
+ */
+function domClassName(node) {
+ return node.className ? "" + node.className : "";
+}
+
+/**
+ * Adds a class name to the class attribute of the given node.
+ *
+ * @param {Element} node DOM element to modify.
+ * @param {String} className Class name to add.
+ */
+function domAddClass(node, className) {
+ var name = domClassName(node);
+ if (name) {
+ var cn = name.split(/\s+/);
+ var found = false;
+ for (var i = 0; i < jsLength(cn); ++i) {
+ if (cn[i] == className) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ cn.push(className);
+ }
+
+ node.className = cn.join(' ');
+ } else {
+ node.className = className;
+ }
+}
+
+/**
+ * Removes a class name from the class attribute of the given node.
+ *
+ * @param {Element} node DOM element to modify.
+ * @param {String} className Class name to remove.
+ */
+function domRemoveClass(node, className) {
+ var c = domClassName(node);
+ if (!c || c.indexOf(className) == -1) {
+ return;
+ }
+ var cn = c.split(/\s+/);
+ for (var i = 0; i < jsLength(cn); ++i) {
+ if (cn[i] == className) {
+ cn.splice(i--, 1);
+ }
+ }
+ node.className = cn.join(' ');
+}
+
+/**
+ * Checks if a node belongs to a style class.
+ *
+ * @param {Element} node DOM element to test.
+ * @param {String} className Class name to check for.
+ * @return {Boolean} Node belongs to style class.
+ */
+function domTestClass(node, className) {
+ var cn = domClassName(node).split(/\s+/);
+ for (var i = 0; i < jsLength(cn); ++i) {
+ if (cn[i] == className) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Inserts a new child before a given sibling.
+ *
+ * @param {Node} newChild Node to insert.
+ * @param {Node} oldChild Sibling node.
+ * @return {Node} Reference to new child.
+ */
+function domInsertBefore(newChild, oldChild) {
+ return oldChild.parentNode.insertBefore(newChild, oldChild);
+}
+
+/**
+ * Appends a new child to the specified (parent) node.
+ *
+ * @param {Element} node Parent element.
+ * @param {Node} child Child node to append.
+ * @return {Node} Newly appended node.
+ */
+function domAppendChild(node, child) {
+ return node.appendChild(child);
+}
+
+/**
+ * Remove a new child from the specified (parent) node.
+ *
+ * @param {Element} node Parent element.
+ * @param {Node} child Child node to remove.
+ * @return {Node} Removed node.
+ */
+function domRemoveChild(node, child) {
+ return node.removeChild(child);
+}
+
+/**
+ * Replaces an old child node with a new child node.
+ *
+ * @param {Node} newChild New child to append.
+ * @param {Node} oldChild Old child to remove.
+ * @return {Node} Replaced node.
+ */
+function domReplaceChild(newChild, oldChild) {
+ return oldChild.parentNode.replaceChild(newChild, oldChild);
+}
+
+/**
+ * Removes a node from the DOM.
+ *
+ * @param {Node} node The node to remove.
+ * @return {Node} The removed node.
+ */
+function domRemoveNode(node) {
+ return domRemoveChild(node.parentNode, node);
+}
+
+/**
+ * Creates a new text node in the given document.
+ *
+ * @param {Document} doc Target document.
+ * @param {String} text Text composing new text node.
+ * @return {Text} Newly constructed text node.
+ */
+function domCreateTextNode(doc, text) {
+ return doc.createTextNode(text);
+}
+
+/**
+ * Creates a new node in the given document
+ *
+ * @param {Document} doc Target document.
+ * @param {String} name Name of new element (i.e. the tag name)..
+ * @return {Element} Newly constructed element.
+ */
+function domCreateElement(doc, name) {
+ return doc.createElement(name);
+}
+
+/**
+ * Creates a new attribute in the given document.
+ *
+ * @param {Document} doc Target document.
+ * @param {String} name Name of new attribute.
+ * @return {Attr} Newly constructed attribute.
+ */
+function domCreateAttribute(doc, name) {
+ return doc.createAttribute(name);
+}
+
+/**
+ * Creates a new comment in the given document.
+ *
+ * @param {Document} doc Target document.
+ * @param {String} text Comment text.
+ * @return {Comment} Newly constructed comment.
+ */
+function domCreateComment(doc, text) {
+ return doc.createComment(text);
+}
+
+/**
+ * Creates a document fragment.
+ *
+ * @param {Document} doc Target document.
+ * @return {DocumentFragment} Resulting document fragment node.
+ */
+function domCreateDocumentFragment(doc) {
+ return doc.createDocumentFragment();
+}
+
+/**
+ * Redirect to document.getElementById
+ *
+ * @param {Document} doc Target document.
+ * @param {String} id Id of requested node.
+ * @return {Element|Null} Resulting element.
+ */
+function domGetElementById(doc, id) {
+ return doc.getElementById(id);
+}
+
+/**
+ * Redirect to window.setInterval
+ *
+ * @param {Window} win Target window.
+ * @param {Function} fun Callback function.
+ * @param {Number} time Time in milliseconds.
+ * @return {Object} Contract id.
+ */
+function windowSetInterval(win, fun, time) {
+ return win.setInterval(fun, time);
+}
+
+/**
+ * Redirect to window.clearInterval
+ *
+ * @param {Window} win Target window.
+ * @param {object} id Contract id.
+ * @return {any} NOTE: Return type unknown?
+ */
+function windowClearInterval(win, id) {
+ return win.clearInterval(id);
+}
+
+/**
+ * Determines whether one node is recursively contained in another.
+ * @param parent The parent node.
+ * @param child The node to look for in parent.
+ * @return parent recursively contains child
+ */
+function containsNode(parent, child) {
+ while (parent != child && child.parentNode) {
+ child = child.parentNode;
+ }
+ return parent == child;
+};
+/**
+ * @fileoverview This file contains javascript utility functions that
+ * do not depend on anything defined elsewhere.
+ *
+ */
+
+/**
+ * Returns the value of the length property of the given object. Used
+ * to reduce compiled code size.
+ *
+ * @param {Array | String} a The string or array to interrogate.
+ * @return {Number} The value of the length property.
+ */
+function jsLength(a) {
+ return a.length;
+}
+
+var min = Math.min;
+var max = Math.max;
+var ceil = Math.ceil;
+var floor = Math.floor;
+var round = Math.round;
+var abs = Math.abs;
+
+/**
+ * Copies all properties from second object to the first. Modifies to.
+ *
+ * @param {Object} to The target object.
+ * @param {Object} from The source object.
+ */
+function copyProperties(to, from) {
+ foreachin(from, function(p) {
+ to[p] = from[p];
+ });
+}
+
+/**
+ * Iterates over the array, calling the given function for each
+ * element.
+ *
+ * @param {Array} array
+ * @param {Function} fn
+ */
+function foreach(array, fn) {
+ var I = jsLength(array);
+ for (var i = 0; i < I; ++i) {
+ fn(array[i], i);
+ }
+}
+
+/**
+ * Safely iterates over all properties of the given object, calling
+ * the given function for each property. If opt_all isn't true, uses
+ * hasOwnProperty() to assure the property is on the object, not on
+ * its prototype.
+ *
+ * @param {Object} object
+ * @param {Function} fn
+ * @param {Boolean} opt_all If true, also iterates over inherited properties.
+ */
+function foreachin(object, fn, opt_all) {
+ for (var i in object) {
+ if (opt_all || !object.hasOwnProperty || object.hasOwnProperty(i)) {
+ fn(i, object[i]);
+ }
+ }
+}
+
+/**
+ * Appends the second array to the first, copying its elements.
+ * Optionally only a slice of the second array is copied.
+ *
+ * @param {Array} a1 Target array (modified).
+ * @param {Array} a2 Source array.
+ * @param {Number} opt_begin Begin of slice of second array (optional).
+ * @param {Number} opt_end End (exclusive) of slice of second array (optional).
+ */
+function arrayAppend(a1, a2, opt_begin, opt_end) {
+ var i0 = opt_begin || 0;
+ var i1 = opt_end || jsLength(a2);
+ for (var i = i0; i < i1; ++i) {
+ a1.push(a2[i]);
+ }
+}
+
+/**
+ * Trim whitespace from begin and end of string.
+ *
+ * @see testStringTrim();
+ *
+ * @param {String} str Input string.
+ * @return {String} Trimmed string.
+ */
+function stringTrim(str) {
+ return stringTrimRight(stringTrimLeft(str));
+}
+
+/**
+ * Trim whitespace from beginning of string.
+ *
+ * @see testStringTrimLeft();
+ *
+ * @param {String} str Input string.
+ * @return {String} Trimmed string.
+ */
+function stringTrimLeft(str) {
+ return str.replace(/^\s+/, "");
+}
+
+/**
+ * Trim whitespace from end of string.
+ *
+ * @see testStringTrimRight();
+ *
+ * @param {String} str Input string.
+ * @return {String} Trimmed string.
+ */
+function stringTrimRight(str) {
+ return str.replace(/\s+$/, "");
+}
+
+/**
+ * Jscompiler wrapper for parseInt() with base 10.
+ *
+ * @param {String} s String repersentation of a number.
+ *
+ * @return {Number} The integer contained in s, converted on base 10.
+ */
+function parseInt10(s) {
+ return parseInt(s, 10);
+}
+/**
+ * @fileoverview A simple formatter to project JavaScript data into
+ * HTML templates. The template is edited in place. I.e. in order to
+ * instantiate a template, clone it from the DOM first, and then
+ * process the cloned template. This allows for updating of templates:
+ * If the templates is processed again, changed values are merely
+ * updated.
+ *
+ * NOTE: IE DOM doesn't have importNode().
+ *
+ * NOTE: The property name "length" must not be used in input
+ * data, see comment in jstSelect_().
+ */
+
+
+/**
+ * Names of jstemplate attributes. These attributes are attached to
+ * normal HTML elements and bind expression context data to the HTML
+ * fragment that is used as template.
+ */
+var ATT_select = 'jsselect';
+var ATT_instance = 'jsinstance';
+var ATT_display = 'jsdisplay';
+var ATT_values = 'jsvalues';
+var ATT_eval = 'jseval';
+var ATT_transclude = 'transclude';
+var ATT_content = 'jscontent';
+
+
+/**
+ * Names of special variables defined by the jstemplate evaluation
+ * context. These can be used in js expression in jstemplate
+ * attributes.
+ */
+var VAR_index = '$index';
+var VAR_this = '$this';
+
+
+/**
+ * Context for processing a jstemplate. The context contains a context
+ * object, whose properties can be referred to in jstemplate
+ * expressions, and it holds the locally defined variables.
+ *
+ * @param {Object} opt_data The context object. Null if no context.
+ *
+ * @param {Object} opt_parent The parent context, from which local
+ * variables are inherited. Normally the context object of the parent
+ * context is the object whose property the parent object is. Null for the
+ * context of the root object.
+ *
+ * @constructor
+ */
+function JsExprContext(opt_data, opt_parent) {
+ var me = this;
+
+ /**
+ * The local context of the input data in which the jstemplate
+ * expressions are evaluated. Notice that this is usually an Object,
+ * but it can also be a scalar value (and then still the expression
+ * $this can be used to refer to it). Notice this can be a scalar
+ * value, including undefined.
+ *
+ * @type {Object}
+ */
+ me.data_ = opt_data;
+
+ /**
+ * The context for variable definitions in which the jstemplate
+ * expressions are evaluated. Other than for the local context,
+ * which replaces the parent context, variable definitions of the
+ * parent are inherited. The special variable $this points to data_.
+ *
+ * @type {Object}
+ */
+ me.vars_ = {};
+ if (opt_parent) {
+ copyProperties(me.vars_, opt_parent.vars_);
+ }
+ this.vars_[VAR_this] = me.data_;
+}
+
+
+/**
+ * Evaluates the given expression in the context of the current
+ * context object and the current local variables.
+ *
+ * @param {String} expr A javascript expression.
+ *
+ * @param {Element} template DOM node of the template.
+ *
+ * @return The value of that expression.
+ */
+JsExprContext.prototype.jseval = function(expr, template) {
+ with (this.vars_) {
+ with (this.data_) {
+ try {
+ return (function() {
+ return eval('[' + expr + '][0]');
+ }).call(template);
+ } catch (e) {
+ return null;
+ }
+ }
+ }
+}
+
+
+/**
+ * Clones the current context for a new context object. The cloned
+ * context has the data object as its context object and the current
+ * context as its parent context. It also sets the $index variable to
+ * the given value. This value usually is the position of the data
+ * object in a list for which a template is instantiated multiply.
+ *
+ * @param {Object} data The new context object.
+ *
+ * @param {Number} index Position of the new context when multiply
+ * instantiated. (See implementation of jstSelect().)
+ *
+ * @return {JsExprContext}
+ */
+JsExprContext.prototype.clone = function(data, index) {
+ var ret = new JsExprContext(data, this);
+ ret.setVariable(VAR_index, index);
+ if (this.resolver_) {
+ ret.setSubTemplateResolver(this.resolver_);
+ }
+ return ret;
+}
+
+
+/**
+ * Binds a local variable to the given value. If set from jstemplate
+ * jsvalue expressions, variable names must start with $, but in the
+ * API they only have to be valid javascript identifier.
+ *
+ * @param {String} name
+ *
+ * @param {Object} value
+ */
+JsExprContext.prototype.setVariable = function(name, value) {
+ this.vars_[name] = value;
+}
+
+
+/**
+ * Sets the function used to resolve the values of the transclude
+ * attribute into DOM nodes. By default, this is jstGetTemplate(). The
+ * value set here is inherited by clones of this context.
+ *
+ * @param {Function} resolver The function used to resolve transclude
+ * ids into a DOM node of a subtemplate. The DOM node returned by this
+ * function will be inserted into the template instance being
+ * processed. Thus, the resolver function must instantiate the
+ * subtemplate as necessary.
+ */
+JsExprContext.prototype.setSubTemplateResolver = function(resolver) {
+ this.resolver_ = resolver;
+}
+
+
+/**
+ * Resolves a sub template from an id. Used to process the transclude
+ * attribute. If a resolver function was set using
+ * setSubTemplateResolver(), it will be used, otherwise
+ * jstGetTemplate().
+ *
+ * @param {String} id The id of the sub template.
+ *
+ * @return {Node} The root DOM node of the sub template, for direct
+ * insertion into the currently processed template instance.
+ */
+JsExprContext.prototype.getSubTemplate = function(id) {
+ return (this.resolver_ || jstGetTemplate).call(this, id);
+}
+
+
+/**
+ * HTML template processor. Data values are bound to HTML templates
+ * using the attributes transclude, jsselect, jsdisplay, jscontent,
+ * jsvalues. The template is modifed in place. The values of those
+ * attributes are JavaScript expressions that are evaluated in the
+ * context of the data object fragment.
+ *
+ * @param {JsExprContext} context Context created from the input data
+ * object.
+ *
+ * @param {Element} template DOM node of the template. This will be
+ * processed in place. After processing, it will still be a valid
+ * template that, if processed again with the same data, will remain
+ * unchanged.
+ */
+function jstProcess(context, template) {
+ var processor = new JstProcessor();
+ processor.run_([ processor, processor.jstProcess_, context, template ]);
+}
+
+
+/**
+ * Internal class used by jstemplates to maintain context.
+ * NOTE: This is necessary to process deep templates in Safari
+ * which has a relatively shallow stack.
+ * @class
+ */
+function JstProcessor() {
+}
+
+
+/**
+ * Runs the state machine, beginning with function "start".
+ *
+ * @param {Array} start The first function to run, in the form
+ * [object, method, args ...]
+ */
+JstProcessor.prototype.run_ = function(start) {
+ var me = this;
+
+ me.queue_ = [ start ];
+ while (jsLength(me.queue_)) {
+ var f = me.queue_.shift();
+ f[1].apply(f[0], f.slice(2));
+ }
+}
+
+
+/**
+ * Appends a function to be called later.
+ * Analogous to calling that function on a subsequent line, or a subsequent
+ * iteration of a loop.
+ *
+ * @param {Array} f A function in the form [object, method, args ...]
+ */
+JstProcessor.prototype.enqueue_ = function(f) {
+ this.queue_.push(f);
+}
+
+
+/**
+ * Implements internals of jstProcess.
+ *
+ * @param {JsExprContext} context
+ *
+ * @param {Element} template
+ */
+JstProcessor.prototype.jstProcess_ = function(context, template) {
+ var me = this;
+
+ var transclude = domGetAttribute(template, ATT_transclude);
+ if (transclude) {
+ var tr = context.getSubTemplate(transclude);
+ if (tr) {
+ domReplaceChild(tr, template);
+ me.enqueue_([ me, me.jstProcess_, context, tr ]);
+ } else {
+ domRemoveNode(template);
+ }
+ return;
+ }
+
+ var select = domGetAttribute(template, ATT_select);
+ if (select) {
+ me.jstSelect_(context, template, select);
+ return;
+ }
+
+ var display = domGetAttribute(template, ATT_display);
+ if (display) {
+ if (!context.jseval(display, template)) {
+ displayNone(template);
+ return;
+ }
+
+ displayDefault(template);
+ }
+
+
+ var values = domGetAttribute(template, ATT_values);
+ if (values) {
+ me.jstValues_(context, template, values);
+ }
+
+ var expressions = domGetAttribute(template, ATT_eval);
+ if (expressions) {
+ foreach(expressions.split(/\s*;\s*/), function(expression) {
+ expression = stringTrim(expression);
+ if (jsLength(expression)) {
+ context.jseval(expression, template);
+ }
+ });
+ }
+
+ var content = domGetAttribute(template, ATT_content);
+ if (content) {
+ me.jstContent_(context, template, content);
+
+ } else {
+ var childnodes = [];
+ for (var i = 0; i < jsLength(template.childNodes); ++i) {
+ if (template.childNodes[i].nodeType == DOM_ELEMENT_NODE) {
+ me.enqueue_(
+ [ me, me.jstProcess_, context, template.childNodes[i] ]);
+ }
+ }
+ }
+}
+
+
+/**
+ * Implements the jsselect attribute: evalutes the value of the
+ * jsselect attribute in the current context, with the current
+ * variable bindings (see JsExprContext.jseval()). If the value is an
+ * array, the current template node is multiplied once for every
+ * element in the array, with the array element being the context
+ * object. If the array is empty, or the value is undefined, then the
+ * current template node is dropped. If the value is not an array,
+ * then it is just made the context object.
+ *
+ * @param {JsExprContext} context The current evaluation context.
+ *
+ * @param {Element} template The currently processed node of the template.
+ *
+ * @param {String} select The javascript expression to evaluate.
+ *
+ * @param {Function} process The function to continue processing with.
+ */
+JstProcessor.prototype.jstSelect_ = function(context, template, select) {
+ var me = this;
+
+ var value = context.jseval(select, template);
+ domRemoveAttribute(template, ATT_select);
+
+ var instance = domGetAttribute(template, ATT_instance);
+ var instance_last = false;
+ if (instance) {
+ if (instance.charAt(0) == '*') {
+ instance = parseInt10(instance.substr(1));
+ instance_last = true;
+ } else {
+ instance = parseInt10(instance);
+ }
+ }
+
+ var multiple = (value !== null &&
+ typeof value == 'object' &&
+ typeof value.length == 'number');
+ var multiple_empty = (multiple && value.length == 0);
+
+ if (multiple) {
+ if (multiple_empty) {
+ if (!instance) {
+ domSetAttribute(template, ATT_select, select);
+ domSetAttribute(template, ATT_instance, '*0');
+ displayNone(template);
+ } else {
+ domRemoveNode(template);
+ }
+
+ } else {
+ displayDefault(template);
+ if (instance === null || instance === "" || instance === undefined ||
+ (instance_last && instance < jsLength(value) - 1)) {
+ var templatenodes = [];
+ var instances_start = instance || 0;
+ for (var i = instances_start + 1; i < jsLength(value); ++i) {
+ var node = domCloneNode(template);
+ templatenodes.push(node);
+ domInsertBefore(node, template);
+ }
+ templatenodes.push(template);
+
+ for (var i = 0; i < jsLength(templatenodes); ++i) {
+ var ii = i + instances_start;
+ var v = value[ii];
+ var t = templatenodes[i];
+
+ me.enqueue_([ me, me.jstProcess_, context.clone(v, ii), t ]);
+ var instanceStr = (ii == jsLength(value) - 1 ? '*' : '') + ii;
+ me.enqueue_(
+ [ null, postProcessMultiple_, t, select, instanceStr ]);
+ }
+
+ } else if (instance < jsLength(value)) {
+ var v = value[instance];
+
+ me.enqueue_(
+ [me, me.jstProcess_, context.clone(v, instance), template]);
+ var instanceStr = (instance == jsLength(value) - 1 ? '*' : '')
+ + instance;
+ me.enqueue_(
+ [ null, postProcessMultiple_, template, select, instanceStr ]);
+ } else {
+ domRemoveNode(template);
+ }
+ }
+ } else {
+ if (value == null) {
+ domSetAttribute(template, ATT_select, select);
+ displayNone(template);
+ } else {
+ me.enqueue_(
+ [ me, me.jstProcess_, context.clone(value, 0), template ]);
+ me.enqueue_(
+ [ null, postProcessSingle_, template, select ]);
+ }
+ }
+}
+
+
+/**
+ * Sets ATT_select and ATT_instance following recursion to jstProcess.
+ *
+ * @param {Element} template The template
+ *
+ * @param {String} select The jsselect string
+ *
+ * @param {String} instanceStr The new value for the jsinstance attribute
+ */
+function postProcessMultiple_(template, select, instanceStr) {
+ domSetAttribute(template, ATT_select, select);
+ domSetAttribute(template, ATT_instance, instanceStr);
+}
+
+
+/**
+ * Sets ATT_select and makes the element visible following recursion to
+ * jstProcess.
+ *
+ * @param {Element} template The template
+ *
+ * @param {String} select The jsselect string
+ */
+function postProcessSingle_(template, select) {
+ domSetAttribute(template, ATT_select, select);
+ displayDefault(template);
+}
+
+
+/**
+ * Implements the jsvalues attribute: evaluates each of the values and
+ * assigns them to variables in the current context (if the name
+ * starts with '$', javascript properties of the current template node
+ * (if the name starts with '.'), or DOM attributes of the current
+ * template node (otherwise). Since DOM attribute values are always
+ * strings, the value is coerced to string in the latter case,
+ * otherwise it's the uncoerced javascript value.
+ *
+ * @param {JsExprContext} context Current evaluation context.
+ *
+ * @param {Element} template Currently processed template node.
+ *
+ * @param {String} valuesStr Value of the jsvalues attribute to be
+ * processed.
+ */
+JstProcessor.prototype.jstValues_ = function(context, template, valuesStr) {
+ var values = valuesStr.split(/\s*;\s*/);
+ for (var i = 0; i < jsLength(values); ++i) {
+ var colon = values[i].indexOf(':');
+ if (colon < 0) {
+ continue;
+ }
+ var label = stringTrim(values[i].substr(0, colon));
+ var value = context.jseval(values[i].substr(colon + 1), template);
+
+ if (label.charAt(0) == '$') {
+ context.setVariable(label, value);
+
+ } else if (label.charAt(0) == '.') {
+ var nameSpaceLabel = label.substr(1).split('.');
+ var nameSpaceObject = template;
+ var nameSpaceDepth = jsLength(nameSpaceLabel);
+ for (var j = 0, J = nameSpaceDepth - 1; j < J; ++j) {
+ var jLabel = nameSpaceLabel[j];
+ if (!nameSpaceObject[jLabel]) {
+ nameSpaceObject[jLabel] = {};
+ }
+ nameSpaceObject = nameSpaceObject[jLabel];
+ }
+ nameSpaceObject[nameSpaceLabel[nameSpaceDepth - 1]] = value;
+ } else if (label) {
+ if (typeof value == 'boolean') {
+ if (value) {
+ domSetAttribute(template, label, label);
+ } else {
+ domRemoveAttribute(template, label);
+ }
+ } else {
+ domSetAttribute(template, label, '' + value);
+ }
+ }
+ }
+}
+
+
+/**
+ * Implements the jscontent attribute. Evalutes the expression in
+ * jscontent in the current context and with the current variables,
+ * and assigns its string value to the content of the current template
+ * node.
+ *
+ * @param {JsExprContext} context Current evaluation context.
+ *
+ * @param {Element} template Currently processed template node.
+ *
+ * @param {String} content Value of the jscontent attribute to be
+ * processed.
+ */
+JstProcessor.prototype.jstContent_ = function(context, template, content) {
+ var value = '' + context.jseval(content, template);
+ if (template.innerHTML == value) {
+ return;
+ }
+ while (template.firstChild) {
+ domRemoveNode(template.firstChild);
+ }
+ var t = domCreateTextNode(ownerDocument(template), value);
+ domAppendChild(template, t);
+}
+
+
+/**
+ * Helps to implement the transclude attribute, and is the initial
+ * call to get hold of a template from its ID.
+ *
+ * @param {String} name The ID of the HTML element used as template.
+ *
+ * @returns {Element} The DOM node of the template. (Only element
+ * nodes can be found by ID, hence it's a Element.)
+ */
+function jstGetTemplate(name) {
+ var section = domGetElementById(document, name);
+ if (section) {
+ var ret = domCloneNode(section);
+ domRemoveAttribute(ret, 'id');
+ return ret;
+ } else {
+ return null;
+ }
+}
+
+window['jstGetTemplate'] = jstGetTemplate;
+window['jstProcess'] = jstProcess;
+window['JsExprContext'] = JsExprContext;
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector/manifest.json b/chrome/common/extensions/docs/examples/api/tabs/inspector/manifest.json
new file mode 100644
index 0000000..1cf3576
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/inspector/manifest.json
@@ -0,0 +1,10 @@
+{
+ "name": "Tab Inspector",
+ "description": "Utility for working with the extension tabs api",
+ "version": "0.1",
+ "permissions": ["tabs"],
+ "background_page": "background.html",
+ "browser_action": {
+ "default_title": "show tab inspector"
+ }
+}
diff --git a/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.html b/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.html
new file mode 100644
index 0000000..159cb27
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.html
@@ -0,0 +1,389 @@
+<html>
+<head>
+<script src="jstemplate_compiled.js" type="text/javascript"></script>
+<script>
+
+tabs = {};
+tabIds = [];
+
+focusedWindowId = undefined;
+currentWindowId = undefined;
+
+function bootStrap() {
+ chrome.windows.getCurrent(function(currentWindow) {
+ currentWindowId = currentWindow.id;
+ chrome.windows.getLastFocused(function(focusedWindow) {
+ focusedWindowId = focusedWindow.id;
+ loadWindowList();
+ });
+ });
+}
+
+function isInt(i) {
+ return (typeof i == "number") && !(i % 1) && !isNaN(i);
+}
+
+function loadWindowList() {
+ chrome.windows.getAll({ populate: true }, function(windowList) {
+ tabs = {};
+ tabIds = [];
+ for (var i = 0; i < windowList.length; i++) {
+ windowList[i].current = (windowList[i].id == currentWindowId);
+ windowList[i].focused = (windowList[i].id == focusedWindowId);
+
+ for (var j = 0; j < windowList[i].tabs.length; j++) {
+ tabIds[tabIds.length] = windowList[i].tabs[j].id;
+ tabs[windowList[i].tabs[j].id] = windowList[i].tabs[j];
+ }
+ }
+
+ var input = new JsExprContext(windowList);
+ var output = document.getElementById('windowList');
+ jstProcess(input, output);
+ });
+}
+
+function updateTabData(id) {
+ var retval = {
+ url: document.getElementById('url_' + id).value,
+ selected: document.getElementById('selected_' + id).value ? true : false
+ }
+
+ return retval;
+}
+
+function updateTab(id){
+ try {
+ chrome.tabs.update(id, updateTabData(id));
+ } catch (e) {
+ alert(e);
+ }
+}
+
+function moveTabData(id) {
+ return {
+ 'index': parseInt(document.getElementById('index_' + id).value),
+ 'windowId': parseInt(document.getElementById('windowId_' + id).value)
+ }
+}
+function moveTab(id) {
+ try {
+ chrome.tabs.move(id, moveTabData(id));
+ } catch (e) {
+ alert(e);
+ }
+}
+
+function createTabData(id) {
+ return {
+ 'index': parseInt(document.getElementById('index_' + id).value),
+ 'windowId': parseInt(document.getElementById('windowId_' + id).value),
+ 'index': parseInt(document.getElementById('index_' + id).value),
+ 'url': document.getElementById('url_' + id).value,
+ 'selected': document.getElementById('selected_' + id).value ? true : false
+ }
+}
+
+function createTab() {
+ var args = createTabData('new')
+
+ if (!isInt(args.windowId))
+ delete args.windowId;
+ if (!isInt(args.index))
+ delete args.index;
+
+ try {
+ chrome.tabs.create(args);
+ } catch (e) {
+ alert(e);
+ }
+}
+
+function updateAll() {
+ try {
+ for (var i = 0; i < tabIds.length; i++) {
+ chrome.tabs.update(tabIds[i], updateTabData(tabIds[i]));
+ }
+ } catch(e) {
+ alert(e);
+ }
+}
+
+function moveAll() {
+ appendToLog('moving all');
+ try {
+ for (var i = 0; i < tabIds.length; i++) {
+ chrome.tabs.move(tabIds[i], moveTabData(tabIds[i]));
+ }
+ } catch(e) {
+ alert(e);
+ }
+}
+
+function removeTab(tabId) {
+ try {
+ chrome.tabs.remove(tabId, function() {
+ appendToLog('tab: ' + tabId + ' removed.');
+ });
+ } catch (e) {
+ alert(e);
+ }
+}
+
+function appendToLog(logLine) {
+ document.getElementById('log')
+ .appendChild(document.createElement('div'))
+ .innerText = "> " + logLine;
+}
+
+function clearLog() {
+ document.getElementById('log').innerText = '';
+}
+
+chrome.windows.onCreated.addListener(function(createInfo) {
+ appendToLog('windows.onCreated -- window: ' + createInfo.id);
+ loadWindowList();
+});
+
+chrome.windows.onFocusChanged.addListener(function(windowId) {
+ focusedWindowId = windowId;
+ appendToLog('windows.onFocusChanged -- window: ' + windowId);
+ loadWindowList();
+});
+
+chrome.windows.onRemoved.addListener(function(windowId) {
+ appendToLog('windows.onRemoved -- window: ' + windowId);
+ loadWindowList();
+});
+
+chrome.tabs.onCreated.addListener(function(tab) {
+ appendToLog('tabs.onCreated -- window: ' + tab.windowId + ' tab: ' + tab.id + ' title: ' + tab.title + ' index ' + tab.index + ' url ' + tab.url);
+ loadWindowList();
+});
+
+chrome.tabs.onAttached.addListener(function(tabId, props) {
+ appendToLog('tabs.onAttached -- window: ' + props.newWindowId + ' tab: ' + tabId + ' index ' + props.newPosition);
+ loadWindowList();
+});
+
+chrome.tabs.onMoved.addListener(function(tabId, props) {
+ appendToLog('tabs.onMoved -- window: ' + props.windowId + ' tab: ' + tabId + ' from ' + props.fromIndex + ' to ' + props.toIndex);
+ loadWindowList();
+});
+
+function refreshTab(tabId) {
+ chrome.tabs.get(tabId, function(tab) {
+ var input = new JsExprContext(tab);
+ var output = document.getElementById('tab_' + tab.id);
+ jstProcess(input, output);
+ appendToLog('tab refreshed -- tabId: ' + tab.id + ' url: ' + tab.url);
+ });
+}
+
+chrome.tabs.onUpdated.addListener(function(tabId, props) {
+ appendToLog('tabs.onUpdated -- tab: ' + tabId + ' status ' + props.status + ' url ' + props.url);
+ refreshTab(tabId);
+});
+
+chrome.tabs.onDetached.addListener(function(tabId, props) {
+ appendToLog('tabs.onDetached -- window: ' + props.oldWindowId + ' tab: ' + tabId + ' index ' + props.oldPosition);
+ loadWindowList();
+});
+
+chrome.tabs.onSelectionChanged.addListener(function(tabId, props) {
+ appendToLog('tabs.onSelectionChanged -- window: ' + props.windowId + ' tab: ' + tabId);
+ loadWindowList();
+});
+
+chrome.tabs.onRemoved.addListener(function(tabId) {
+ appendToLog('tabs.onRemoved -- tab: ' + tabId);
+ loadWindowList();
+});
+
+function createWindow() {
+ var args = {
+ 'left': parseInt(document.getElementById('new_window_left').value),
+ 'top': parseInt(document.getElementById('new_window_top').value),
+ 'width': parseInt(document.getElementById('new_window_width').value),
+ 'height': parseInt(document.getElementById('new_window_height').value),
+ 'url': document.getElementById('new_window_url').value
+ }
+
+ if (!isInt(args.left))
+ delete args.left;
+ if (!isInt(args.top))
+ delete args.top;
+ if (!isInt(args.width))
+ delete args.width;
+ if (!isInt(args.height))
+ delete args.height;
+ if (!args.url)
+ delete args.url;
+
+ try {
+ chrome.windows.create(args);
+ } catch(e) {
+ alert(e);
+ }
+}
+
+function refreshWindow(windowId) {
+ chrome.windows.get(windowId, function(window) {
+ chrome.tabs.getAllInWindow(window.id, function(tabList) {
+ window.tabs = tabList;
+ var input = new JsExprContext(window);
+ var output = document.getElementById('window_' + window.id);
+ jstProcess(input, output);
+ appendToLog('window refreshed -- windowId: ' + window.id + ' tab count:' + window.tabs.length);
+ });
+ });
+}
+
+function updateWindowData(id) {
+ var retval = {
+ left: parseInt(document.getElementById('left_' + id).value),
+ top: parseInt(document.getElementById('top_' + id).value),
+ width: parseInt(document.getElementById('width_' + id).value),
+ height: parseInt(document.getElementById('height_' + id).value)
+ }
+ if (!isInt(retval.left))
+ delete retval.left;
+ if (!isInt(retval.top))
+ delete retval.top;
+ if (!isInt(retval.width))
+ delete retval.width;
+ if (!isInt(retval.height))
+ delete retval.height;
+
+ return retval;
+}
+
+function updateWindow(id){
+ try {
+ chrome.windows.update(id, updateWindowData(id));
+ } catch (e) {
+ alert(e);
+ }
+}
+
+function removeWindow(windowId) {
+ try {
+ chrome.windows.remove(windowId, function() {
+ appendToLog('window: ' + windowId + ' removed.');
+ });
+ } catch (e) {
+ alert(e);
+ }
+}
+
+function refreshSelectedTab(windowId) {
+ chrome.tabs.getSelected(windowId, function(tab) {
+ var input = new JsExprContext(tab);
+ var output = document.getElementById('tab_' + tab.id);
+ jstProcess(input, output);
+ appendToLog('selected tab refreshed -- tabId: ' + tab.id + ' url:' + tab.url);
+ });
+}
+
+</script>
+</head>
+ <body onload="bootStrap();">
+ <div id="windowList">
+ <div style="background-color: #AAEEEE; margin: 4px; padding: 8px; margin: 20px" jsselect="$this"
+ jsvalues="id:'window_' + id">
+ <div style="font-style: italic; width: 80px; display: inline-block">
+ Window: <span jscontent="id"></span>
+ </div>
+ <div style="display: inline-block">
+ left: <input style="width: 60px" type="text" jsvalues="value:$this.left;id:'left_' + id" />
+ top: <input style="width: 60px" type="text" jsvalues="value:$this.top;id:'top_' + id" />
+ width: <input style="width: 60px" type="text" jsvalues="value:$this.width;id:'width_' + id" />
+ height: <input style="width: 60px" type="text" jsvalues="value:$this.height;id:'height_' + id" />
+ <input type="checkbox" jsvalues="checked:focused; id:'focused_' + id" /> Focused
+ <input type="checkbox" jsvalues="checked:current; id:'current_' + id" /> Current
+ <button onclick="refreshWindow(this.jstdata);" jsvalues=".jstdata:id">Refresh</button>
+ </div>
+ <div id="tabList">
+ <div jsselect="tabs">
+ <div style="background-color: #EEEEEE; margin: 8px; padding: 4px" jsvalues="id:'tab_' + id">
+ <div style="margin: 8px">
+ <div style="font-style: italic; width: 80px; display: inline-block" jscontent="'TabId: ' + id"></div>
+ <div style="width: 300px; display: inline-block">
+ index: <input style="width: 20px" type="text" jsvalues="value:$this.index;id:'index_' + id" />
+ windowId: <input style="width: 20px" type="text" jsvalues="value:windowId;id:'windowId_' + id" />
+ <button onclick="moveTab(this.jstdata);" jsvalues=".jstdata:id">Move</button>
+ <button onclick="refreshTab(this.jstdata);" jsvalues=".jstdata:id">Refresh</button>
+ </div>
+ </div>
+ <div style="margin: 8px">
+ <div>
+ <div style="width: 40px; display:inline-block">title:</div>
+ <input style="width: 90%" type="text" jsvalues="value:title;id:'title_' + id" />
+ </div>
+ <div>
+ <div style="width: 40px; display:inline-block">url:</div>
+ <input style="width: 90%" type="text" jsvalues="value:url;id:'url_' + id" />
+ </div>
+ <div><input type="checkbox" jsvalues="checked:selected; id:'selected_' + id" /> Selected</div>
+ </div>
+ <button onclick="updateTab(this.jstdata)" jsvalues=".jstdata:id">Update Tab</button>
+ <button onclick="removeTab(this.jstdata);" jsvalues=".jstdata:id">Close Tab</button>
+ </div>
+ </div>
+ </div>
+ <button onclick="updateWindow(this.jstdata);" jsvalues=".jstdata:id">Update Window</button>
+ <button onclick="removeWindow(this.jstdata);" jsvalues=".jstdata:id">Close Window</button>
+ <button onclick="refreshSelectedTab(this.jstdata);" jsvalues=".jstdata:id">Refresh Selected Tab</button>
+ </div>
+ </div>
+ <div style="background-color: #EEEEBB; margin: 20px; padding: 8px">
+ <h3 style="text-align: center; margin: 8px"> Create Window</h3>
+ <div style="margin: 8px">
+ <div style="width: 300px; display: inline-block">
+ left: <input style="width: 20px" type="text" id="new_window_left" />
+ top: <input style="width: 20px" type="text" id="new_window_top" />
+ width: <input style="width: 20px" type="text" id="new_window_width" />
+ height: <input style="width: 20px" type="text" id="new_window_height" />
+ </div>
+ </div>
+ <div style="margin: 8px">
+ <div>
+ <div style="width: 40px; display:inline-block">url:</div>
+ <input style="width: 90%" type="text" id="new_window_url" />
+ </div>
+ </div>
+ <button onclick="createWindow();">Create</button>
+ </div>
+ <div style="background-color: #EEEEAA; margin: 20px; padding: 8px">
+ <h3 style="text-align: center; margin: 8px"> Create Tab</h3>
+ <div style="margin: 8px">
+ <div style="width: 300px; display: inline-block">
+ index: <input style="width: 20px" type="text" id="index_new" />
+ windowId: <input style="width: 20px" type="text" id="windowId_new" />
+ <button onclick="moveTab(this.jstdata);" jsvalues=".jstdata:id">Move</button>
+ </div>
+ </div>
+ <div style="margin: 8px">
+ <div>
+ <div style="width: 40px; display:inline-block">title:</div>
+ <input style="width: 90%" type="text" id="title_new" />
+ </div>
+ <div>
+ <div style="width: 40px; display:inline-block">url:</div>
+ <input style="width: 90%" type="text" id="url_new" />
+ </div>
+ <div><input type="checkbox" id="selected_new" /> Selected</div>
+ </div>
+ <button onclick="createTab();">Create</button>
+ </div>
+ <div style="margin: 20px;">
+ <button onclick="loadWindowList();">Refresh</button>
+ <button onclick="updateAll();">Update All</button>
+ <button onclick="moveAll();">Move All</button>
+ <button onclick="clearLog();">-->Clear Log</button>
+ <button onclick="chrome.windows.create();">New Window</button>
+ </div>
+ <div id="log" style="background-color: #EEAAEE; margin: 20px; padding: 8px">
+ </div>
+ </body>
+</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot.zip b/chrome/common/extensions/docs/examples/api/tabs/screenshot.zip
new file mode 100644
index 0000000..63c3cb6
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.html b/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.html
new file mode 100644
index 0000000..2955688
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/background.html
@@ -0,0 +1,10 @@
+
+<html>
+<head>
+<script src='screenshot.js' type='text/javascript' />
+<script>
+</script>
+</head>
+<body>
+</body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/camera.png b/chrome/common/extensions/docs/examples/api/tabs/screenshot/camera.png
new file mode 100644
index 0000000..be26c39
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/camera.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json b/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json
new file mode 100644
index 0000000..37fdbf0
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/manifest.json
@@ -0,0 +1,11 @@
+{
+ "name": "Test Screenshot Extension",
+ "version": "1.0",
+ "description": "Demonstrate screenshot functionality in the chrome.tabs api.",
+ "background_page": "background.html",
+ "browser_action": {
+ "default_icon": "camera.png",
+ "default_title": "Take a screen shot!"
+ },
+ "permissions": ["tabs"]
+}
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.html b/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.html
new file mode 100644
index 0000000..408d13d
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.html
@@ -0,0 +1,14 @@
+<html>
+<script>
+function setScreenshotUrl(url) {
+ document.getElementById('target').src = url;
+}
+</script>
+<body>
+ Image here:
+ <p>
+ <img id="target" src="white.png" width="640" height="480">
+ <p>
+ End image
+ </body>
+</html>
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.js b/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.js
new file mode 100644
index 0000000..a003719
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/screenshot.js
@@ -0,0 +1,48 @@
+// To make sure we can uniquely identify each screenshot tab, add an id as a
+// query param to the url that displays the screenshot.
+var id = 100;
+
+function takeScreenshot() {
+ chrome.tabs.captureVisibleTab(null, function(img) {
+ var screenshotUrl = img;
+ var viewTabUrl = [chrome.extension.getURL('screenshot.html'),
+ '?id=', id++].join('');
+
+ chrome.tabs.create({url: viewTabUrl}, function(tab) {
+ var targetId = tab.id;
+
+ var addSnapshotImageToTab = function(tabId, changedProps) {
+ // We are waiting for the tab we opened to finish loading.
+ // Check that the the tab's id matches the tab we opened,
+ // and that the tab is done loading.
+ if (tabId != targetId || changedProps.status != "complete")
+ return;
+
+ // Passing the above test means this is the event we were waiting for.
+ // There is nothing we need to do for future onUpdated events, so we
+ // use removeListner to stop geting called when onUpdated events fire.
+ chrome.tabs.onUpdated.removeListener(addSnapshotImageToTab);
+
+ // Look through all views to find the window which will display
+ // the screenshot. The url of the tab which will display the
+ // screenshot includes a query parameter with a unique id, which
+ // ensures that exactly one view will have the matching URL.
+ var views = chrome.extension.getViews();
+ for (var i = 0; i < views.length; i++) {
+ var view = views[i];
+ if (view.location.href == viewTabUrl) {
+ view.setScreenshotUrl(screenshotUrl);
+ break;
+ }
+ }
+ };
+ chrome.tabs.onUpdated.addListener(addSnapshotImageToTab);
+
+ });
+ });
+}
+
+// Listen for a click on the camera icon. On that click, take a screenshot.
+chrome.browserAction.onClicked.addListener(function(tab) {
+ takeScreenshot();
+});
diff --git a/chrome/common/extensions/docs/examples/api/tabs/screenshot/white.png b/chrome/common/extensions/docs/examples/api/tabs/screenshot/white.png
new file mode 100644
index 0000000..06d8aca
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/white.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows.zip b/chrome/common/extensions/docs/examples/api/windows/merge_windows.zip
new file mode 100644
index 0000000..8614c06
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/NOTICE b/chrome/common/extensions/docs/examples/api/windows/merge_windows/NOTICE
new file mode 100644
index 0000000..d86114b
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows/NOTICE
@@ -0,0 +1,2 @@
+This extension uses icons based on the famfamfam silk series.
+http://www.famfamfam.com/lab/icons/silk/ \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/arrow_in.png b/chrome/common/extensions/docs/examples/api/windows/merge_windows/arrow_in.png
new file mode 100644
index 0000000..745c651
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows/arrow_in.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/background.html b/chrome/common/extensions/docs/examples/api/windows/merge_windows/background.html
new file mode 100644
index 0000000..6575af8
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows/background.html
@@ -0,0 +1,49 @@
+<html>
+ <head>
+ <script>
+ var targetWindow = null;
+ var tabCount = 0;
+
+ function start(tab) {
+ chrome.windows.getCurrent(getWindows);
+ }
+
+ function getWindows(win) {
+ targetWindow = win;
+ chrome.tabs.getAllInWindow(targetWindow.id, getTabs);
+ }
+
+ function getTabs(tabs) {
+ tabCount = tabs.length;
+ // We require all the tab information to be populated.
+ chrome.windows.getAll({"populate" : true}, moveTabs);
+ }
+
+ function moveTabs(windows) {
+ var numWindows = windows.length;
+ var tabPosition = tabCount;
+
+ for (var i = 0; i < numWindows; i++) {
+ var win = windows[i];
+
+ if (targetWindow.id != win.id) {
+ var numTabs = win.tabs.length;
+
+ for (var j = 0; j < numTabs; j++) {
+ var tab = win.tabs[j];
+
+ // Move the tab into the window that triggered the browser action.
+ chrome.tabs.move(tab.id,
+ {"windowId": targetWindow.id, "index": tabPosition});
+
+ tabPosition++;
+ }
+ }
+ }
+ }
+
+ // Set up a click handler so that we can merge all the windows.
+ chrome.browserAction.onClicked.addListener(start);
+ </script>
+ </head>
+</html> \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/manifest.json b/chrome/common/extensions/docs/examples/api/windows/merge_windows/manifest.json
new file mode 100644
index 0000000..5868092
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows/manifest.json
@@ -0,0 +1,15 @@
+{
+ "name": "Merge Windows",
+ "version": "1.0.0.0",
+ "description": "Merges all of the browser's windows into the current window",
+ "icons": {
+ "48": "merge_windows_48.png",
+ "128": "merge_windows_128.png"
+ },
+ "background_page": "background.html",
+ "browser_action": {
+ "default_icon": "arrow_in.png",
+ "default_title": "Merge Windows"
+ },
+ "permissions": ["tabs"]
+} \ No newline at end of file
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_128.png b/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_128.png
new file mode 100644
index 0000000..00bea8e
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_128.png
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_48.png b/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_48.png
new file mode 100644
index 0000000..2d8f727
--- /dev/null
+++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_48.png
Binary files differ