diff options
author | Kristian Monsen <kristianm@google.com> | 2010-10-27 13:32:00 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-10-27 13:33:18 +0100 |
commit | 8ae428e0fb7feea16d79853f29447469a93bedff (patch) | |
tree | 055de38ae24a222549cf0c8e4f68f2e679388551 /chrome/common/extensions/docs/examples/api | |
parent | fb45465643e6355ea14862fb898dcb4b51175bea (diff) | |
download | external_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')
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 Binary files differnew file mode 100644 index 0000000..7460329 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/bookmarks/basic.zip 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 Binary files differnew file mode 100644 index 0000000..ac58aa1 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red.zip 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 Binary files differnew file mode 100644 index 0000000..9a79a46 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/icon.png 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 Binary files differnew file mode 100644 index 0000000..95c9329 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/print.zip 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 Binary files differnew file mode 100644 index 0000000..d145964 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/print/print_16x16.png 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 Binary files differnew file mode 100644 index 0000000..f424d96 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path.zip 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 Binary files differnew file mode 100644 index 0000000..9a79a46 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon1.png 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 Binary files differnew file mode 100644 index 0000000..8d3f710 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon2.png 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 Binary files differnew file mode 100644 index 0000000..2d9dec3 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon3.png 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 Binary files differnew file mode 100644 index 0000000..896fc36 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon4.png 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 Binary files differnew file mode 100644 index 0000000..a5afa25 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/set_icon_path/icon5.png 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 Binary files differnew file mode 100644 index 0000000..e76e94b --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color.zip 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 Binary files differnew file mode 100644 index 0000000..1f1c906 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/browserAction/set_page_color/icon.png 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 Binary files differnew file mode 100644 index 0000000..443d83b --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/contextMenus/basic.zip 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 Binary files differnew file mode 100644 index 0000000..edd8163 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/cookies.zip 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 Binary files differnew file mode 100644 index 0000000..ca72eca --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/cookies/cookie.png 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 Binary files differnew file mode 100644 index 0000000..970cf68 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/history/showHistory.zip diff --git a/chrome/common/extensions/docs/examples/api/history/showHistory/clock.png b/chrome/common/extensions/docs/examples/api/history/showHistory/clock.png Binary files differnew file mode 100644 index 0000000..08682cf --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/history/showHistory/clock.png 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 Binary files differnew file mode 100644 index 0000000..f809b4b --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/i18n/cld.zip 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 Binary files differnew file mode 100644 index 0000000..a67a0ae --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/i18n/getMessage.zip 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 Binary files differnew file mode 100644 index 0000000..9a79a46 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/i18n/getMessage/icon.png 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 Binary files differnew file mode 100644 index 0000000..ff33a9a --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple.zip 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 Binary files differnew file mode 100644 index 0000000..1c961db --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-128.png 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 Binary files differnew file mode 100644 index 0000000..a10636f --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-16.png 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 Binary files differnew file mode 100644 index 0000000..32f265a --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-19.png 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 Binary files differnew file mode 100644 index 0000000..bee88b7 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/idle/idle_simple/sample-48.png diff --git a/chrome/common/extensions/docs/examples/api/infobars/sandwichbar.zip b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar.zip Binary files differnew file mode 100644 index 0000000..5a5c9f6 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar.zip 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 Binary files differnew file mode 100644 index 0000000..a233154 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-128.png 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 Binary files differnew file mode 100644 index 0000000..86f3b3c --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-16.png 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 Binary files differnew file mode 100644 index 0000000..e84dc86 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-19.png 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 Binary files differnew file mode 100644 index 0000000..d7f2324 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/infobars/sandwichbar/sandwich-48.png diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer.zip b/chrome/common/extensions/docs/examples/api/messaging/timer.zip Binary files differnew file mode 100644 index 0000000..8143322 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/messaging/timer.zip diff --git a/chrome/common/extensions/docs/examples/api/messaging/timer/clock.png b/chrome/common/extensions/docs/examples/api/messaging/timer/clock.png Binary files differnew file mode 100644 index 0000000..7889ac0 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/messaging/timer/clock.png 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 Binary files differnew file mode 100644 index 0000000..2013295 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/notifications.zip diff --git a/chrome/common/extensions/docs/examples/api/notifications/128.png b/chrome/common/extensions/docs/examples/api/notifications/128.png Binary files differnew file mode 100644 index 0000000..7013aa9 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/notifications/128.png diff --git a/chrome/common/extensions/docs/examples/api/notifications/16.png b/chrome/common/extensions/docs/examples/api/notifications/16.png Binary files differnew file mode 100644 index 0000000..669c791 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/notifications/16.png diff --git a/chrome/common/extensions/docs/examples/api/notifications/48.png b/chrome/common/extensions/docs/examples/api/notifications/48.png Binary files differnew file mode 100644 index 0000000..8a151ad --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/notifications/48.png diff --git a/chrome/common/extensions/docs/examples/api/notifications/64.png b/chrome/common/extensions/docs/examples/api/notifications/64.png Binary files differnew file mode 100644 index 0000000..347e28f --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/notifications/64.png 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 Binary files differnew file mode 100644 index 0000000..fdebe41 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/omnibox.zip 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 Binary files differnew file mode 100644 index 0000000..ea5f6c7 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/override/blank_ntp.zip 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™</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 Binary files differnew file mode 100644 index 0000000..bdd90fd --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/override/override_igoogle.zip 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 Binary files differnew file mode 100644 index 0000000..714f749 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content.zip 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 Binary files differnew file mode 100644 index 0000000..a233154 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-128.png 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 Binary files differnew file mode 100644 index 0000000..e84dc86 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-19.png 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 Binary files differnew file mode 100644 index 0000000..d7f2324 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_content/sandwich-48.png 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 Binary files differnew file mode 100644 index 0000000..25365b6 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url.zip 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 Binary files differnew file mode 100644 index 0000000..fbfe538 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-128.png 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 Binary files differnew file mode 100644 index 0000000..91679f0 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-19.png 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 Binary files differnew file mode 100644 index 0000000..59e9935 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/pageaction_by_url/icon-48.png 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 Binary files differnew file mode 100644 index 0000000..9bd5927 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/set_icon.zip 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 Binary files differnew file mode 100644 index 0000000..9a79a46 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon1.png 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 Binary files differnew file mode 100644 index 0000000..8d3f710 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/pageAction/set_icon/icon2.png 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 Binary files differnew file mode 100644 index 0000000..08659d1 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/processes/show_tabs.zip 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 Binary files differnew file mode 100644 index 0000000..9a79a46 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/processes/show_tabs/icon.png 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 Binary files differnew file mode 100644 index 0000000..36a74ad --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/tabs/inspector.zip 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 Binary files differnew file mode 100644 index 0000000..63c3cb6 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot.zip 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 Binary files differnew file mode 100644 index 0000000..be26c39 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/camera.png 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 Binary files differnew file mode 100644 index 0000000..06d8aca --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/tabs/screenshot/white.png diff --git a/chrome/common/extensions/docs/examples/api/windows/merge_windows.zip b/chrome/common/extensions/docs/examples/api/windows/merge_windows.zip Binary files differnew file mode 100644 index 0000000..8614c06 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows.zip 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 Binary files differnew file mode 100644 index 0000000..745c651 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows/arrow_in.png 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 Binary files differnew file mode 100644 index 0000000..00bea8e --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_128.png 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 Binary files differnew file mode 100644 index 0000000..2d8f727 --- /dev/null +++ b/chrome/common/extensions/docs/examples/api/windows/merge_windows/merge_windows_48.png |