diff options
author | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-18 01:01:31 +0000 |
---|---|---|
committer | kalman@chromium.org <kalman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-18 01:01:31 +0000 |
commit | 09d2e1d94dab63e571d527fb716c0fc86dd51206 (patch) | |
tree | e5873d71bd228df7b2e7084488e7fcb6cb379779 /chrome/common | |
parent | 241d7040f857063736abe23acad2840f7f9ec931 (diff) | |
download | chromium_src-09d2e1d94dab63e571d527fb716c0fc86dd51206.zip chromium_src-09d2e1d94dab63e571d527fb716c0fc86dd51206.tar.gz chromium_src-09d2e1d94dab63e571d527fb716c0fc86dd51206.tar.bz2 |
Copy the extension docs content from chrome/common/extensions/docs/server2 into
just c/c/e/docs.
This is an interim patch while we switch over the server to look there for the
content, after which we'll delete the old content.
BUG=147714
TBR=aa@chromium.org
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@157264 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/common')
443 files changed, 20208 insertions, 0 deletions
diff --git a/chrome/common/extensions/docs/static/css/api.css b/chrome/common/extensions/docs/static/css/api.css new file mode 100644 index 0000000..50f94a8 --- /dev/null +++ b/chrome/common/extensions/docs/static/css/api.css @@ -0,0 +1,53 @@ +/* Copyright (c) 2012 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. + */ + +.type_name, +.variable, +.property { + font-style: italic; +} + +#gc-pagecontent table { + border-collapse: collapse; +} + +#gc-pagecontent th { + text-align: left; + padding: 6px 12px; +} + +#gc-pagecontent td { + padding: 6px 12px; + border: 1px solid #36C; + vertical-align: top; +} + +.api_reference div.summary { + border: 1px solid #93B4D9; + font-family: "Courier New", courier, monospace; + padding: 0.5em 0.5em 0.5em 2em; + text-indent: -1.5em; + background-color: #CADEF4; + margin-top: 1em; +} + +/* This style is used because types with functions prefix the function with the + * type name, using a lowercase first letter. + */ +.api_reference div.lower:first-letter { + text-transform: lowercase; +} + +.api_reference div.description { + margin-left: 2em; +} + +div.summary .subdued { + color: #7594B8; +} + +.optional { + color: #7D7D7D; +} diff --git a/chrome/common/extensions/docs/static/css/index.css b/chrome/common/extensions/docs/static/css/index.css new file mode 100644 index 0000000..0be984d --- /dev/null +++ b/chrome/common/extensions/docs/static/css/index.css @@ -0,0 +1,43 @@ +/* Copyright (c) 2012 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. + */ + +#gc-pagecontent { + margin: 0; +} + +#index table { + margin: 0 0 0 1px; + border-color: #36C; + border-spacing: 0; + clear: right; + border-collapse: collapse; + line-height: 125%; +} + +#index table.columns td { + padding: 0 1em 0 0; +} + +#index table.columns td p { + margin: 1em 0 0 0; + padding: 0; +} + +#index td { + padding: 6px 12px; + border 1px solid #36C; + background-color: white; + text-align: left; + vertical-align: top; +} + +#index td ul, #index td ol { + margin: 0 0 1em 15px; + padding: 0; +} + +#howDoIStart { + width: 330px; +} diff --git a/chrome/common/extensions/docs/static/css/prettify.css b/chrome/common/extensions/docs/static/css/prettify.css new file mode 100644 index 0000000..bba79c7 --- /dev/null +++ b/chrome/common/extensions/docs/static/css/prettify.css @@ -0,0 +1,51 @@ +/* Pretty printing styles. Used with prettify.js. */ + +/* SPAN elements with the classes below are added by prettyprint. */ +.pln { color: #000 } /* plain text */ + +@media screen { + .str { color: #080 } /* string content */ + .kwd { color: #008 } /* a keyword */ + .com { color: #800 } /* a comment */ + .typ { color: #606 } /* a type name */ + .lit { color: #066 } /* a literal value */ + /* punctuation, lisp open bracket, lisp close bracket */ + .pun, .opn, .clo { color: #660 } + .tag { color: #008 } /* a markup tag name */ + .atn { color: #606 } /* a markup attribute name */ + .atv { color: #080 } /* a markup attribute value */ + .dec, .var { color: #606 } /* a declaration; a variable name */ + .fun { color: red } /* a function name */ +} + +/* Use higher contrast and text-weight for printable form. */ +@media print, projection { + .str { color: #060 } + .kwd { color: #006; font-weight: bold } + .com { color: #600; font-style: italic } + .typ { color: #404; font-weight: bold } + .lit { color: #044 } + .pun, .opn, .clo { color: #440 } + .tag { color: #006; font-weight: bold } + .atn { color: #404 } + .atv { color: #060 } +} + +pre.prettyprint { } + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { margin-top: 0; margin-bottom: 0 } /* IE indents via margin-left */ +li.L0, +li.L1, +li.L2, +li.L3, +li.L5, +li.L6, +li.L7, +li.L8 { list-style-type: none } +/* Alternate shading for lines */ +li.L1, +li.L3, +li.L5, +li.L7, +li.L9 { background: #eee } diff --git a/chrome/common/extensions/docs/static/css/print.css b/chrome/common/extensions/docs/static/css/print.css new file mode 100644 index 0000000..b2820b1 --- /dev/null +++ b/chrome/common/extensions/docs/static/css/print.css @@ -0,0 +1,11 @@ +/* Chrome extensions developer guide - styles for printing */ + +/* Make preformatted text wrap + (ref: http://myy.helia.fi/~karte/pre-wrap-css3-mozilla-opera-ie.html) */ +pre { + white-space: pre-wrap; /* css-3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} diff --git a/chrome/common/extensions/docs/static/css/samples.css b/chrome/common/extensions/docs/static/css/samples.css new file mode 100644 index 0000000..f9823ab --- /dev/null +++ b/chrome/common/extensions/docs/static/css/samples.css @@ -0,0 +1,34 @@ +#controls { + margin: 10px 0; + background: #EEE; + padding: 10px; + border-radius: 10px; +} + +#search_input { + width: 30em; +} + +.label { + font-weight: bold; +} + +td.label { + min-width: 150px; + text-align: right; + vertical-align: top; + padding-right: 10px; +} + +.sample { + position: relative; + padding-left: 80px; +} + +img.icon { + position: absolute; + width: 64px; + height: 64px; + left: 0; + top: 40px; +} diff --git a/chrome/common/extensions/docs/static/css/site.css b/chrome/common/extensions/docs/static/css/site.css new file mode 100644 index 0000000..af548cf --- /dev/null +++ b/chrome/common/extensions/docs/static/css/site.css @@ -0,0 +1,441 @@ +/* Copyright (c) 2012 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. + */ + +.hidden { + display: none; +} + +body { + color: #333; + font: 13px/22px 'Open Sans',arial,sans-serif; + font-weight: 400; + background-color: white; + margin: auto; + padding: 0; +} + +p { + margin: 1em 0 0 0; + color: #767676; + font-size: 14px; +} + +p.note, +p.caution, +p.warning { + margin: 1em 0 0 0; + padding: .2em .5em .2em .9em; + background-color: #F5F5F5; + border-top: 1px solid; + border-bottom: 1px solid; + overflow: hidden; +} + +p.note { + border-color: #36C; +} +p.caution { + border-color: #FC3; +} +p.warning { + border-color: #A03; +} + +p.warning em, +p.warning strong { + color: #A03; +} + +a, a:link { + text-decoration: none; + color: #39F; + font-weight: 600; +} + +a:visited { + color: #194c7f; +} + +a:active, +a:hover { + color: #236bb2; +} + +#toc a { + color: black; +} + +ol, ul { + color: #767676; +} + +#header { + margin: auto; + max-width: 1160px; + padding: 0 50px; + position: relative; + height: 60px; +} + +#logo { + position: relative; + padding-top: 10px; + z-index: 2; +} + +#logo img { + padding: 10px 0; +} + +#cse { + width: 400px; + padding-top: 5px; + z-index: 1; + position: absolute; + right: 50px; +} + +/* + * Without a border, the results from the custom search are hard to tell apart + * from the rest of the content + */ +.gsc-resultsbox-visible { + border-left: 1px solid #E9E9E9; + border-right: 1px solid #E9E9E9; + border-bottom: 1px solid #E9E9E9; +} + +li { + margin: .3em 0 0 1.5em; + padding: 0; +} + +ol li { + margin-top: 1em; +} + +img { + border: none; + padding: 10px 0; +} + +code, +pre { + font-family: monospace; + color: #080; +} + +code { + font-size: 10pt; +} + +pre { + font-size: 10pt; + background-color: #F5F5F5; + margin: 1em 0 0 0; + padding: .99em; + overflow: auto; + word-wrap: break-word; +} + +pre a { + text-decoration: underline!important; +} + +pre b { + background: yellow; +} + +dt { + font-weight: bold; + margin: .75em 0 0 0; +} + +dl { + margin: 0; +} + +dd { + margin: .4em 0 0 2em; + padding: 0; + font-weight: normal; +} + +.displayModeWarning { + background-color: #FF7735; + color: white; + font-weight: bold; + padding: 6px 8px; +} + +span.displayModeWarning { + margin-right: 2px; +} + +#gc-container { + margin: auto; + max-width: 1160px; + padding: 0 50px; + position: relative; + height: auto; +} + +#gc-topnav { + font-size: 1em; + margin: auto; + max-width: 1160px; + padding: 0; + white-space: nowrap; + background-color: white; + border-top: 1px solid #E5E5E5; + border-bottom: 1px solid #E5E5E5; +} + +#gc-topnav h1 { + font-size: 1.5em; + line-height: 1.3em; + font-weight: bold; + background-color: transparent; + border: 0; + margin: 0; + padding: 0 0 0 14px; + float: left; + border-top: 10px solid white; +} + +#gc-topnav li { + font-weight: 600; + height: 45px; + text-transform: uppercase; + white-space: nowrap; + display: inline-block; + margin: 0; + padding: 0; +} + +#gc-topnav ul { + font-size: 12px; + height: 45px; + text-align: right; + list-style: none; + margin: 0; +} + +#gc-topnav li a { + color: #333; +} +#gc-topnav li a:hover { + color: #39f; +} + +#gc-topnav div { + border-top: 10px solid white; + margin: 0 30px; + position: relative; + height: 29px; +} + +.pageData { + display: none; +} + +#gc-pagecontent { + margin: 30px 0 100px 250px; +} + +#gc-pagecontent h2 { + border-top: 1px solid #CCC; + font-size: 170%; + font-weight: normal; + margin: 2em 0 0 0; + padding: 40px 0; +} + +#gc-pagecontent h3 { + font-size: 130%; + font-weight: bold; + margin: 1.5em 0 0 0; + top: 0em; +} + +#gc-pagecontent h4 { + font-size: 110%; + margin: .7em 0 0 0; + position: relative; + top: .4em; +} + +#gc-pagecontent h1.page_title, +#gc-pagecontent h2.page_title { + line-height: 130%; + font-size: 320%; + margin: 0; + padding: .8em 0 0; + border: none; + background: none; + font-weight: normal; +} + +#gc-footer { + clear: both; + margin: auto; + color: #666; + max-width: 1160px; + padding: 0 50px; +} + +#gc-footer .text { + text-align: center; + padding: 30px 0; + margin: 0 0 0 0; +} + +#gc-sidebar { + margin: 0; + margin-top: 2.5em; + width: 180px; + float: left; +} + +/* Sidebar link/button styling. */ +#gc-sidebar span, +#gc-sidebar a { + color: #767676; + display: block; + position: relative; + font-weight: normal; +} +#gc-sidebar a:visited { + color: #767676; +} +#gc-sidebar a:hover, +#gc-sidebar a.selected { + color: #39F; +} +#gc-sidebar a.button { + color: #767676; +} +#gc-sidebar span.level2, +#gc-sidebar a.level2 { + font-weight: bold; +} + +#gc-sidebar .toggleIndicator { + position: absolute; + right: 0; + top: 3px; + background: url(../images/toggle_sprite.png) no-repeat 0 0; + height: 8px; + width: 8px; +} +#gc-sidebar .toggleIndicator.toggled { + background-position: 0 -9px; +} + +/* Sidebar list styling. */ +#gc-sidebar ul { + list-style: none; + padding: 0; +} +#gc-sidebar ul.level2 { + margin-left: 10px; + padding-top: 10px; +} +#gc-sidebar ul.level3 { + margin-left: 20px; + padding-top: 10px; + list-style: url(../images/sidearrow.png); +} + +/* Sidebar list element styling. */ +#gc-sidebar li { + margin: 0; + padding: 8px 0; + line-height: 120%; +} +#gc-sidebar li.level2 { + border-top: 1px solid #E5E5E5; +} + +#gc-toc div.line { + border-top: thin solid #FAFAFA; + height: 1px; + margin: 1.3em 1em 0 0; + padding: 0; +} + +#toc { + background-color: #F5F5F5; + float: right; + margin: 5px 0px 5px 20px; + padding: 5px; + width: 250px; + word-break: break-word; +} + +#toc * { + padding: 0; + list-style: none; + font-weight: 600; +} + +#toc h2 { + font-weight: bold; + font-size: 100%; + margin: 0; + border: none; + padding: 0; +} + +#toc ol { + margin: 1em 0 0 0; +} + +#toc ol li { + margin: .5em 0 .5em 1em; + line-height: 1.2em; +} + +#toc ol li ol { + margin: 0; +} + +#toc ol li ol li { + margin: .5em 0 .5em 1em; +} + +.filtered_item { + line-height: 6px; +} + +#filtered_apis { + margin-top: 5px; +} + +#skipto { + display: none; +} + +input.gsc-search-button.gsc-search-button-v2 { + padding: 8px 30px; + margin-top: 5px; +} + +div.gsc-control-cse { + margin: 0; + padding: 0; + position: relative; + z-index: 2; +} + +td.gsc-input { + padding: 0 0; +} + +div.gsc-input-box { + height: 30px; + width: 250px; + float: right; +} diff --git a/chrome/common/extensions/docs/static/images/a11y/focus-outline-2.png b/chrome/common/extensions/docs/static/images/a11y/focus-outline-2.png Binary files differnew file mode 100644 index 0000000..b8c96c1 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/a11y/focus-outline-2.png diff --git a/chrome/common/extensions/docs/static/images/a11y/focus-outline.png b/chrome/common/extensions/docs/static/images/a11y/focus-outline.png Binary files differnew file mode 100644 index 0000000..aea6551 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/a11y/focus-outline.png diff --git a/chrome/common/extensions/docs/static/images/a11y/standard-html-controls.png b/chrome/common/extensions/docs/static/images/a11y/standard-html-controls.png Binary files differnew file mode 100644 index 0000000..518ee8e --- /dev/null +++ b/chrome/common/extensions/docs/static/images/a11y/standard-html-controls.png diff --git a/chrome/common/extensions/docs/static/images/applifecycle.png b/chrome/common/extensions/docs/static/images/applifecycle.png Binary files differnew file mode 100644 index 0000000..2b04cdb --- /dev/null +++ b/chrome/common/extensions/docs/static/images/applifecycle.png diff --git a/chrome/common/extensions/docs/static/images/bookmarks.png b/chrome/common/extensions/docs/static/images/bookmarks.png Binary files differnew file mode 100644 index 0000000..d8e56f8 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/bookmarks.png diff --git a/chrome/common/extensions/docs/static/images/browser-action.png b/chrome/common/extensions/docs/static/images/browser-action.png Binary files differnew file mode 100644 index 0000000..82ebe33 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/browser-action.png diff --git a/chrome/common/extensions/docs/static/images/calculator-128.png b/chrome/common/extensions/docs/static/images/calculator-128.png Binary files differnew file mode 100644 index 0000000..85963f3 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/calculator-128.png diff --git a/chrome/common/extensions/docs/static/images/calculator-16.png b/chrome/common/extensions/docs/static/images/calculator-16.png Binary files differnew file mode 100644 index 0000000..0d9135e --- /dev/null +++ b/chrome/common/extensions/docs/static/images/calculator-16.png diff --git a/chrome/common/extensions/docs/static/images/chrome_logo.gif b/chrome/common/extensions/docs/static/images/chrome_logo.gif Binary files differnew file mode 100644 index 0000000..c6bcc7b --- /dev/null +++ b/chrome/common/extensions/docs/static/images/chrome_logo.gif diff --git a/chrome/common/extensions/docs/static/images/console-button.gif b/chrome/common/extensions/docs/static/images/console-button.gif Binary files differnew file mode 100644 index 0000000..387b4e8 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/console-button.gif diff --git a/chrome/common/extensions/docs/static/images/container.png b/chrome/common/extensions/docs/static/images/container.png Binary files differnew file mode 100644 index 0000000..d83ade0 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/container.png diff --git a/chrome/common/extensions/docs/static/images/devtools-1.gif b/chrome/common/extensions/docs/static/images/devtools-1.gif Binary files differnew file mode 100644 index 0000000..012500a --- /dev/null +++ b/chrome/common/extensions/docs/static/images/devtools-1.gif diff --git a/chrome/common/extensions/docs/static/images/devtools-2.gif b/chrome/common/extensions/docs/static/images/devtools-2.gif Binary files differnew file mode 100644 index 0000000..ec85912 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/devtools-2.gif diff --git a/chrome/common/extensions/docs/static/images/devtools-3.gif b/chrome/common/extensions/docs/static/images/devtools-3.gif Binary files differnew file mode 100644 index 0000000..40deb03 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/devtools-3.gif diff --git a/chrome/common/extensions/docs/static/images/devtools-audits-category.png b/chrome/common/extensions/docs/static/images/devtools-audits-category.png Binary files differnew file mode 100644 index 0000000..b05fc7d --- /dev/null +++ b/chrome/common/extensions/docs/static/images/devtools-audits-category.png diff --git a/chrome/common/extensions/docs/static/images/devtools-audits-results.png b/chrome/common/extensions/docs/static/images/devtools-audits-results.png Binary files differnew file mode 100644 index 0000000..9185055 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/devtools-audits-results.png diff --git a/chrome/common/extensions/docs/static/images/devtools-localvars.gif b/chrome/common/extensions/docs/static/images/devtools-localvars.gif Binary files differnew file mode 100644 index 0000000..2640c7d --- /dev/null +++ b/chrome/common/extensions/docs/static/images/devtools-localvars.gif diff --git a/chrome/common/extensions/docs/static/images/devtools-panels.png b/chrome/common/extensions/docs/static/images/devtools-panels.png Binary files differnew file mode 100644 index 0000000..93cbdfa --- /dev/null +++ b/chrome/common/extensions/docs/static/images/devtools-panels.png diff --git a/chrome/common/extensions/docs/static/images/editor.png b/chrome/common/extensions/docs/static/images/editor.png Binary files differnew file mode 100644 index 0000000..f584a06 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/editor.png diff --git a/chrome/common/extensions/docs/static/images/filebrowserhandler.png b/chrome/common/extensions/docs/static/images/filebrowserhandler.png Binary files differnew file mode 100644 index 0000000..746ddad --- /dev/null +++ b/chrome/common/extensions/docs/static/images/filebrowserhandler.png diff --git a/chrome/common/extensions/docs/static/images/hello-world-small.png b/chrome/common/extensions/docs/static/images/hello-world-small.png Binary files differnew file mode 100644 index 0000000..567b167 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/hello-world-small.png diff --git a/chrome/common/extensions/docs/static/images/hello-world.png b/chrome/common/extensions/docs/static/images/hello-world.png Binary files differnew file mode 100644 index 0000000..11ba245 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/hello-world.png diff --git a/chrome/common/extensions/docs/static/images/i18n-after-1.gif b/chrome/common/extensions/docs/static/images/i18n-after-1.gif Binary files differnew file mode 100644 index 0000000..76650e2 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/i18n-after-1.gif diff --git a/chrome/common/extensions/docs/static/images/i18n-after-2.gif b/chrome/common/extensions/docs/static/images/i18n-after-2.gif Binary files differnew file mode 100644 index 0000000..031d119 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/i18n-after-2.gif diff --git a/chrome/common/extensions/docs/static/images/i18n-before.gif b/chrome/common/extensions/docs/static/images/i18n-before.gif Binary files differnew file mode 100644 index 0000000..7691e91 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/i18n-before.gif diff --git a/chrome/common/extensions/docs/static/images/i18n-hierarchy.gif b/chrome/common/extensions/docs/static/images/i18n-hierarchy.gif Binary files differnew file mode 100644 index 0000000..2854072 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/i18n-hierarchy.gif diff --git a/chrome/common/extensions/docs/static/images/i18n-strings.gif b/chrome/common/extensions/docs/static/images/i18n-strings.gif Binary files differnew file mode 100644 index 0000000..d82df88 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/i18n-strings.gif diff --git a/chrome/common/extensions/docs/static/images/index/gmail-small.png b/chrome/common/extensions/docs/static/images/index/gmail-small.png Binary files differnew file mode 100644 index 0000000..0e70bc0 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/index/gmail-small.png diff --git a/chrome/common/extensions/docs/static/images/index/html5app.png b/chrome/common/extensions/docs/static/images/index/html5app.png Binary files differnew file mode 100644 index 0000000..62582b6 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/index/html5app.png diff --git a/chrome/common/extensions/docs/static/images/infobar.png b/chrome/common/extensions/docs/static/images/infobar.png Binary files differnew file mode 100644 index 0000000..d375fa1 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/infobar.png diff --git a/chrome/common/extensions/docs/static/images/jstransferrequests.png b/chrome/common/extensions/docs/static/images/jstransferrequests.png Binary files differnew file mode 100644 index 0000000..0211322 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/jstransferrequests.png diff --git a/chrome/common/extensions/docs/static/images/load_after.png b/chrome/common/extensions/docs/static/images/load_after.png Binary files differnew file mode 100644 index 0000000..cbeb8b3 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/load_after.png diff --git a/chrome/common/extensions/docs/static/images/load_after_small.png b/chrome/common/extensions/docs/static/images/load_after_small.png Binary files differnew file mode 100644 index 0000000..204cd90 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/load_after_small.png diff --git a/chrome/common/extensions/docs/static/images/mvc.png b/chrome/common/extensions/docs/static/images/mvc.png Binary files differnew file mode 100644 index 0000000..efc1009 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/mvc.png diff --git a/chrome/common/extensions/docs/static/images/notification-linux.png b/chrome/common/extensions/docs/static/images/notification-linux.png Binary files differnew file mode 100644 index 0000000..e0d06a4 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/notification-linux.png diff --git a/chrome/common/extensions/docs/static/images/notification-mac.png b/chrome/common/extensions/docs/static/images/notification-mac.png Binary files differnew file mode 100644 index 0000000..dfa1d92 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/notification-mac.png diff --git a/chrome/common/extensions/docs/static/images/notification-windows.png b/chrome/common/extensions/docs/static/images/notification-windows.png Binary files differnew file mode 100644 index 0000000..673d917 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/notification-windows.png diff --git a/chrome/common/extensions/docs/static/images/ntp-blank.png b/chrome/common/extensions/docs/static/images/ntp-blank.png Binary files differnew file mode 100644 index 0000000..79ad292 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/ntp-blank.png diff --git a/chrome/common/extensions/docs/static/images/ntp-default.png b/chrome/common/extensions/docs/static/images/ntp-default.png Binary files differnew file mode 100644 index 0000000..4aa15c1 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/ntp-default.png diff --git a/chrome/common/extensions/docs/static/images/omnibox.png b/chrome/common/extensions/docs/static/images/omnibox.png Binary files differnew file mode 100644 index 0000000..c8d3bb4 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/omnibox.png diff --git a/chrome/common/extensions/docs/static/images/overview/arch-1.gif b/chrome/common/extensions/docs/static/images/overview/arch-1.gif Binary files differnew file mode 100644 index 0000000..16d4a84 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/overview/arch-1.gif diff --git a/chrome/common/extensions/docs/static/images/overview/arch-2.gif b/chrome/common/extensions/docs/static/images/overview/arch-2.gif Binary files differnew file mode 100644 index 0000000..e6281c5 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/overview/arch-2.gif diff --git a/chrome/common/extensions/docs/static/images/overview/arch-3.gif b/chrome/common/extensions/docs/static/images/overview/arch-3.gif Binary files differnew file mode 100644 index 0000000..968f388 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/overview/arch-3.gif diff --git a/chrome/common/extensions/docs/static/images/overview/arch-cs.gif b/chrome/common/extensions/docs/static/images/overview/arch-cs.gif Binary files differnew file mode 100644 index 0000000..619ea2a --- /dev/null +++ b/chrome/common/extensions/docs/static/images/overview/arch-cs.gif diff --git a/chrome/common/extensions/docs/static/images/overview/browser-action-with-popup.png b/chrome/common/extensions/docs/static/images/overview/browser-action-with-popup.png Binary files differnew file mode 100644 index 0000000..b1ca45e --- /dev/null +++ b/chrome/common/extensions/docs/static/images/overview/browser-action-with-popup.png diff --git a/chrome/common/extensions/docs/static/images/overview/browser-action.png b/chrome/common/extensions/docs/static/images/overview/browser-action.png Binary files differnew file mode 100644 index 0000000..8bf54df --- /dev/null +++ b/chrome/common/extensions/docs/static/images/overview/browser-action.png diff --git a/chrome/common/extensions/docs/static/images/overview/flash-app.png b/chrome/common/extensions/docs/static/images/overview/flash-app.png Binary files differnew file mode 100644 index 0000000..c3052b4 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/overview/flash-app.png diff --git a/chrome/common/extensions/docs/static/images/overview/page-action.png b/chrome/common/extensions/docs/static/images/overview/page-action.png Binary files differnew file mode 100644 index 0000000..257a233 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/overview/page-action.png diff --git a/chrome/common/extensions/docs/static/images/package-success.gif b/chrome/common/extensions/docs/static/images/package-success.gif Binary files differnew file mode 100644 index 0000000..175a049 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/package-success.gif diff --git a/chrome/common/extensions/docs/static/images/page-action.png b/chrome/common/extensions/docs/static/images/page-action.png Binary files differnew file mode 100644 index 0000000..3e3b391 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/page-action.png diff --git a/chrome/common/extensions/docs/static/images/perms-hw1.png b/chrome/common/extensions/docs/static/images/perms-hw1.png Binary files differnew file mode 100644 index 0000000..5e88b0d --- /dev/null +++ b/chrome/common/extensions/docs/static/images/perms-hw1.png diff --git a/chrome/common/extensions/docs/static/images/perms-hw2-disabled.png b/chrome/common/extensions/docs/static/images/perms-hw2-disabled.png Binary files differnew file mode 100644 index 0000000..1e880ff --- /dev/null +++ b/chrome/common/extensions/docs/static/images/perms-hw2-disabled.png diff --git a/chrome/common/extensions/docs/static/images/perms-hw2.png b/chrome/common/extensions/docs/static/images/perms-hw2.png Binary files differnew file mode 100644 index 0000000..82cee5de --- /dev/null +++ b/chrome/common/extensions/docs/static/images/perms-hw2.png diff --git a/chrome/common/extensions/docs/static/images/perms-optional.png b/chrome/common/extensions/docs/static/images/perms-optional.png Binary files differnew file mode 100644 index 0000000..91b3f27 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/perms-optional.png diff --git a/chrome/common/extensions/docs/static/images/play-button.gif b/chrome/common/extensions/docs/static/images/play-button.gif Binary files differnew file mode 100644 index 0000000..9039660 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/play-button.gif diff --git a/chrome/common/extensions/docs/static/images/sample-default-icon.png b/chrome/common/extensions/docs/static/images/sample-default-icon.png Binary files differnew file mode 100644 index 0000000..04f4319 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/sample-default-icon.png diff --git a/chrome/common/extensions/docs/static/images/sidearrow.png b/chrome/common/extensions/docs/static/images/sidearrow.png Binary files differnew file mode 100644 index 0000000..6da307a --- /dev/null +++ b/chrome/common/extensions/docs/static/images/sidearrow.png diff --git a/chrome/common/extensions/docs/static/images/tabs.png b/chrome/common/extensions/docs/static/images/tabs.png Binary files differnew file mode 100644 index 0000000..1a039d2 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/tabs.png diff --git a/chrome/common/extensions/docs/static/images/themes-1.gif b/chrome/common/extensions/docs/static/images/themes-1.gif Binary files differnew file mode 100644 index 0000000..fb4bff8 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/themes-1.gif diff --git a/chrome/common/extensions/docs/static/images/themes-2.gif b/chrome/common/extensions/docs/static/images/themes-2.gif Binary files differnew file mode 100644 index 0000000..17f35ae --- /dev/null +++ b/chrome/common/extensions/docs/static/images/themes-2.gif diff --git a/chrome/common/extensions/docs/static/images/themes-3.gif b/chrome/common/extensions/docs/static/images/themes-3.gif Binary files differnew file mode 100644 index 0000000..ed55160 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/themes-3.gif diff --git a/chrome/common/extensions/docs/static/images/todos.png b/chrome/common/extensions/docs/static/images/todos.png Binary files differnew file mode 100644 index 0000000..8b7e4ae --- /dev/null +++ b/chrome/common/extensions/docs/static/images/todos.png diff --git a/chrome/common/extensions/docs/static/images/toggle_sprite.png b/chrome/common/extensions/docs/static/images/toggle_sprite.png Binary files differnew file mode 100644 index 0000000..d41a5bd --- /dev/null +++ b/chrome/common/extensions/docs/static/images/toggle_sprite.png diff --git a/chrome/common/extensions/docs/static/images/toolsmenu.gif b/chrome/common/extensions/docs/static/images/toolsmenu.gif Binary files differnew file mode 100644 index 0000000..1b0b1e5 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/toolsmenu.gif diff --git a/chrome/common/extensions/docs/static/images/tut_analytics/screenshot01.png b/chrome/common/extensions/docs/static/images/tut_analytics/screenshot01.png Binary files differnew file mode 100644 index 0000000..52792f6 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/tut_analytics/screenshot01.png diff --git a/chrome/common/extensions/docs/static/images/tut_analytics/screenshot02.png b/chrome/common/extensions/docs/static/images/tut_analytics/screenshot02.png Binary files differnew file mode 100644 index 0000000..e590de6 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/tut_analytics/screenshot02.png diff --git a/chrome/common/extensions/docs/static/images/tut_analytics/screenshot03.png b/chrome/common/extensions/docs/static/images/tut_analytics/screenshot03.png Binary files differnew file mode 100644 index 0000000..5a4efc8 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/tut_analytics/screenshot03.png diff --git a/chrome/common/extensions/docs/static/images/tut_analytics/screenshot04.png b/chrome/common/extensions/docs/static/images/tut_analytics/screenshot04.png Binary files differnew file mode 100644 index 0000000..4c82be0 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/tut_analytics/screenshot04.png diff --git a/chrome/common/extensions/docs/static/images/update-success.gif b/chrome/common/extensions/docs/static/images/update-success.gif Binary files differnew file mode 100644 index 0000000..66e3e8b --- /dev/null +++ b/chrome/common/extensions/docs/static/images/update-success.gif diff --git a/chrome/common/extensions/docs/static/images/webrequestapi.png b/chrome/common/extensions/docs/static/images/webrequestapi.png Binary files differnew file mode 100644 index 0000000..7ae2cee --- /dev/null +++ b/chrome/common/extensions/docs/static/images/webrequestapi.png diff --git a/chrome/common/extensions/docs/static/images/windows.png b/chrome/common/extensions/docs/static/images/windows.png Binary files differnew file mode 100644 index 0000000..6abfb01 --- /dev/null +++ b/chrome/common/extensions/docs/static/images/windows.png diff --git a/chrome/common/extensions/docs/static/js/branch.js b/chrome/common/extensions/docs/static/js/branch.js new file mode 100644 index 0000000..3b70fc3 --- /dev/null +++ b/chrome/common/extensions/docs/static/js/branch.js @@ -0,0 +1,26 @@ +// Copyright (c) 2012 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. + +(function() { + var branchChooser = document.getElementById('branchChooser'); + // No branch chooser on stable (for example). + if (!branchChooser) + return; + + branchChooser.addEventListener('change', function() { + var value = event.target.value; + if (!value) + return; + var current_branch = window.bootstrap.branchInfo.current; + var path = window.location.pathname.split('/'); + if (path[0] == '') + path = path.slice(1); + var index = path.indexOf(current_branch); + if (index != -1) + path[index] = value; + else + path.splice(0, 0, value); + window.location = '/' + path.join('/'); + }); +})() diff --git a/chrome/common/extensions/docs/static/js/filter.js b/chrome/common/extensions/docs/static/js/filter.js new file mode 100644 index 0000000..02b5aa3 --- /dev/null +++ b/chrome/common/extensions/docs/static/js/filter.js @@ -0,0 +1,35 @@ +// Copyright (c) 2012 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. + +// This is used for the search box on the left navigation bar. The APIs are +// filtered and displayed based on what the user is typing in the box. +(function() { + var search_box = document.getElementById('api_search'); + var filtered_apis = document.getElementById('filtered_apis'); + + function filterAPIs() { + var search_text = search_box.value.toLowerCase(); + var apis = window.bootstrap.api_names; + if (!search_text) { + filtered_apis.style.display = 'none'; + return; + } + var api_list = '' + for (var i = 0; i < apis.length; ++i) { + if (apis[i].name.toLowerCase().indexOf(search_text) != -1) + api_list += '<li class="filtered_item"><a href="' + apis[i].name + + '.html">' + apis[i].name + '</a></li>' + } + if (api_list != filtered_apis.innerHtml) + filtered_apis.innerHTML = api_list; + if (!api_list) + filtered_apis.style.display = 'none'; + else + filtered_apis.style.display = ''; + } + + filtered_apis.style.display = 'none'; + search_box.addEventListener('search', filterAPIs); + search_box.addEventListener('keyup', filterAPIs); +})(); diff --git a/chrome/common/extensions/docs/static/js/prettify.js b/chrome/common/extensions/docs/static/js/prettify.js new file mode 100644 index 0000000..eef5ad7 --- /dev/null +++ b/chrome/common/extensions/docs/static/js/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c< +f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&& +(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r= +{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length, +t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b=== +"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value", +m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m= +a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue= +j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m, +250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit", +PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})(); diff --git a/chrome/common/extensions/docs/static/js/samples.js b/chrome/common/extensions/docs/static/js/samples.js new file mode 100644 index 0000000..cdc9496 --- /dev/null +++ b/chrome/common/extensions/docs/static/js/samples.js @@ -0,0 +1,29 @@ +// Copyright (c) 2012 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. + +(function() { + var search_box = document.getElementById('search_input'); + var samples = document.getElementsByClassName('sample'); + + function filterSamples() { + var search_text = search_box.value.toLowerCase(); + for (var i = 0; i < samples.length; ++i) { + var sample = samples[i] + if (sample.getAttribute('tags').toLowerCase().indexOf(search_text) < 0) + sample.style.display = 'none'; + else + sample.style.display = ''; + } + } + search_box.addEventListener('search', filterSamples); + search_box.addEventListener('keyup', filterSamples); + + var api_filter_items = document.getElementById('api_filter_items'); + api_filter_items.addEventListener('click', function(event) { + if (event.target instanceof HTMLAnchorElement) { + search_box.value = 'chrome.' + event.target.innerText; + filterSamples(); + } + }); +})(); diff --git a/chrome/common/extensions/docs/static/js/sidebar.js b/chrome/common/extensions/docs/static/js/sidebar.js new file mode 100644 index 0000000..ec97cb7 --- /dev/null +++ b/chrome/common/extensions/docs/static/js/sidebar.js @@ -0,0 +1,85 @@ +// Copyright (c) 2012 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. + +/** + * Adds toggle controls to the sidebar list. + * + * Controls are inserted as the first children of list items in the sidebar + * which contain only text (not a link). Handlers are set up so that when a + * toggle control is clicked, any <ul> elements who are siblings of the + * control are hidden/revealed as appropriate given the control's state. + * + * If a list item possesses the class 'selected' its ancestor <ul> is + * revealed by default (it represents the current page). + */ +(function() { + var sidebar = document.getElementById('gc-sidebar'); + if (!sidebar) + return; + + // Figure out which link matches the current page so it can be styled + // differently. + var pathParts = document.location.pathname.replace(/\/+$/, '').split('/') + Array.prototype.forEach.call(sidebar.getElementsByTagName('a'), + function(link) { + if (link.getAttribute('href') != pathParts[pathParts.length - 1]) + return; + link.className = 'selected'; + link.removeAttribute('href'); + }); + + // Go through the items on the sidebar and add toggles. + Array.prototype.forEach.call(sidebar.querySelectorAll('[toggleable]'), + function(toggleable) { + var buttonContent = toggleable.previousElementSibling; + if (!buttonContent) { + console.warn('Cannot toggle %s, no previous sibling', toggleable); + return; + } + + var button = document.createElement('a'); + button.className = 'button'; + var toggleIndicator = document.createElement('div'); + toggleIndicator.className = 'toggleIndicator'; + + var isToggled = false; + function toggle() { + if (isToggled) { + toggleable.classList.add('hidden'); + toggleIndicator.classList.remove('toggled'); + } else { + toggleable.classList.remove('hidden'); + toggleIndicator.classList.add('toggled'); + } + isToggled = !isToggled; + } + + // TODO(kalman): needs a button role for accessibility? + button.setAttribute('href', 'javascript:void(0)'); + button.addEventListener('click', toggle); + buttonContent.parentElement.insertBefore(button, buttonContent); + button.appendChild(buttonContent); + button.appendChild(toggleIndicator); + + // Leave the toggle open if the selected link is a child. + if (toggleable.querySelector('.selected')) + toggle(); + else + toggleable.classList.add('hidden'); + }); + + // Each level of the sidebar is displayed differently. Rather than trying + // to nest CSS selectors in a crazy way, programmatically assign levels + // to them. + function addNestLevels(node, currentLevel) { + node.classList.add('level' + currentLevel); + if (node.tagName == 'UL') + currentLevel++; + Array.prototype.forEach.call(node.children, function(child) { + addNestLevels(child, currentLevel); + }); + } + + addNestLevels(sidebar, 1); +})() diff --git a/chrome/common/extensions/docs/templates/articles/a11y.html b/chrome/common/extensions/docs/templates/articles/a11y.html new file mode 100644 index 0000000..1a6036c --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/a11y.html @@ -0,0 +1,466 @@ +<h1>Accessibility (a11y)</h1> + + +<p> +When you design an extension, +try to make it as accessible as possible +to people with disabilities such as +visual impairment, hearing loss, and limited dexterity. +</p> + +<p> +Everyone — not just people with special needs — +can benefit from the alternative access modes +that accessible extensions provide. +For example, keyboard shortcuts are important +for blind people and people with limited dexterity, +but they also help power users get things done +more quickly without using a mouse. +Captions and transcripts give deaf people access to audio content, +but they are also useful to language learners. +</p> + +<p> +People can interact with your extension in a variety of ways. +They might use a standard monitor, keyboard, and mouse, +or they might use a screen magnifier and just a keyboard. +Another possibility is a <em>screen reader</em>, +an assistive application tool that interprets +what's displayed onscreen +for a blind or visually impaired user. +A screen reader might speak out loud or produce Braille output. +</p> + +<p> +Although you can't predict what tools people will use, +by following a few simple guidelines +you can write an extension that is +more likely to be accessible to more people. +The guidelines on this page aren't going to +make your extension accessible for absolutely everyone, +but they're a good starting point. +</p> + + +<h2 id="controls">Use accessible UI controls</h2> + +<p> +First, use UI controls that support accessibility. +The easiest way to get an accessible control is to use a +standard HTML control. +If you need to build a custom control, +keep in mind that it's much easier +to make the control accessible from the beginning +than to go back and add accessibility support later. +</p> + +<h3 id="htmlcontrols">Standard controls</h3> + +<p> +Try to use standard HTML UI controls whenever possible. +Standard HTML controls (shown in the following figure) +are keyboard accessible, scale easily, +and are generally understood by screen readers. +</p> + +<img src="{{static}}/images/a11y/standard-html-controls.png" + width="550" height="350" + alt="Screenshots and code for button, checkbox, radio, text, select/option, and link"> + + +<h3 id="aria">ARIA in custom controls</h3> + +<p> +ARIA is a specification for making UI controls accessible to screen readers +by means of a standard set of DOM attributes. +These attributes provide clues to the screen reader +about the function and current state of controls on a web page. +ARIA is a +<a href=" http://www.w3.org/WAI/intro/aria">work in progress at the W3C</a>. +</p> + +<p> +Adding ARIA support to custom controls in your extension +involves modifying DOM elements to add attributes +Google Chrome uses +to raise events during user interaction. +Screen readers respond to these events +and describe the function of the control. +The DOM attributes specified by ARIA are classified into +<em>roles</em>, <em>states</em>, and <em>properties</em>. +</p> + +<p> +The ARIA attribute <em>role</em> +is an indication of the control type +and describes the way the control should behave. +It is expressed with the DOM attribute <code>role</code>, +with a value set to one of the pre-defined ARIA role strings. +Because ARIA roles are static, +the role attribute should not change its value. +</p> + +<p> +The <a href="http://www.w3.org/WAI/PF/aria/roles">ARIA Role Specification</a> +holds detailed information on how to pick the correct role. +For example, if your extension includes a toolbar, +set the <code>role</code> attribute of the toolbar's DOM element as follows: +</p> + +<pre> +<div role="toolbar"> +</pre> + +<p> +ARIA attributes are also used to describe +the current state and properties of controls of a particular role. +A <em>state</em> is dynamic and should be updated during user interaction. +For example, a control with the role "checkbox" +could be in the states "checked" or "unchecked". +A <em>property</em> is not generally dynamic, +but is similar to a state +in that it expresses specific information about a control. +For more information on ARIA states and properties, +refer to the +<a href="http://www.w3.org/TR/wai-aria/states_and_properties">W3C States and Properties specification</a>. +</p> + + +<p class="note"> +<b>Note:</b> +You don't have to use +all of the states and properties available for a particular role. +</p> + +<p> +Here's an example of adding +the ARIA property <code>aria-activedescendant</code> +to the example toolbar control: +</p> + +<pre> +<div role="toolbar" tabindex="0" aria-activedescendant="button1"> +</pre> + +<p> +The +<a href="http://www.w3.org/WAI/PF/aria/states_and_properties#aria-activedescendant"><code>aria-activedescendant</code></a> +property specifies which child of the toolbar receives focus +when the toolbar receives focus. +In this example, the toolbar's first button +(which has the <code>id</code> "button1") +is the child that gets focus. +The code <code>tabindex="0"</code> +specifies that the toolbar +receives focus in document order. +</p> + +<p> +Here's the complete specification for the example toolbar: +</p> + +<pre> +<div role="toolbar" tabindex="0" aria-activedescendant="button1"> + <img src="buttoncut.png" role="button" alt="cut" id="button1"> + <img src="buttoncopy.png" role="button" alt="copy" id="button2"> + <img src="buttonpaste.png" role="button" alt="paste" id="button3"> +</div> +</pre> + +<p> +Once ARIA roles, states, and properties are added to the DOM of a control, +Google Chrome raises the appropriate events to the screen reader. +Because ARIA support is still a work in progress, +Google Chrome might not raise an event for every ARIA property, +and screen readers might not recognize all of the events being raised. +You can find more information on ARIA support in Google Chrome in the +<a href="http://www.chromium.org/developers/design-documents/accessibility#TOC-WAI-ARIA-Support">Chromium Accessibility Design Document</a>. +</p> + +<p> +For a quick tutorial on adding ARIA controls to custom controls, see +<a href="http://www.w3.org/2010/Talks/www2010-dsr-diy-aria/">Dave Raggett's presentation from WWW2010</a>. + +<h3 id="focus">Focus in custom controls</h3> + +<p> +Make sure that operation and navigation controls of your extension +can receive keyboard focus. +Operation controls might include +buttons, trees, and list boxes. +Navigation controls might include tabs and menu bars. +</p> + +<p> +By default, the only elements in the HTML DOM +that can receive keyboard focus +are anchors, buttons, and form controls. +However, setting the HTML attribute <code>tabIndex</code> to <code>0</code> +places DOM elements in the default tab sequence, +enabling them to receive keyboard focus. +For example: +</p> + +<pre> +<em>element</em>.tabIndex = 0 +</pre> + +<p> +Setting <code>tabIndex = -1</code> removes the element from the tab sequence +but still allows the element to receive keyboard focus programmatically. +Here's an example of setting keyboard focus: +</p> + +<pre> +<em>element</em>.focus(); +</pre> + +<p> +Ensuring that your custom UI controls include keyboard support +is important not only for users who don't use the mouse +but also because screen readers use keyboard focus +to determine which control to describe. +</p> + +<h2 id="keyboard"> Support keyboard access </h2> + +<p> +People should be able to use your extension +even if they can't or don't want to use a mouse. +</p> + +<h3 id="navigation"> Navigation </h3> + +<p> +Check that the user can navigate between +the different parts of your extension +without using the mouse. +Also check that any popups on page actions or browser actions +are keyboard navigable. +</p> + +<p id="builtin"> +On Windows, you can use <b>Shift+Alt+T</b> +to switch the keyboard focus to the toolbar, +which lets you navigate to the icons of page actions and browser actions. +The help topic +<a href="http://www.google.com/support/chrome/bin/static.py?hl=en&page=guide.cs&guide=25799&from=25799&rd=1">Keyboard and mouse shortcuts</a> +lists all of Google Chrome's keyboard shortcuts; +details about toolbar navigation +are in the section <b>Google Chrome feature shortcuts</b>. +</p> + +<p class="note"> +<b>Note:</b> +The Windows version of Google Chrome 6 was the first +to support keyboard navigation to the toolbar. +Support is also planned for Linux. +On Mac OS X, +access to the toolbar is provided through VoiceOver, +Apple's screenreader. +</p> + +<p> +Make sure that it's easy to see +which part of the interface has keyboard focus. +Usually a focus outline moves around the interface, +but if you’re using CSS heavily this outline might be suppressed +or the contrast might be reduced. +Two examples of focus outline follow. +</p> + +<img src="{{static}}/images/a11y/focus-outline-2.png" + width="200" height="75" + alt="A focus outline on a Search button"> +<br /> +<img src="{{static}}/images/a11y/focus-outline.png" + width="400" height="40" + alt="A focus outline on one of a series of links"> + + +<h3 id="shortcuts"> Shortcuts </h3> + +<p> +Although the most common keyboard navigation strategy involves +using the Tab key to move focus through the extension interface, +that's not always the easiest or most efficient way +to use the interface. +You can make keyboard navigation easier +by providing explicit keyboard shortcuts. +</p> + +<p> +To implement shortcuts, +connect keyboard event listeners to your controls. +A good reference is the DHTML Style Guide Working Group’s +<a href="http://dev.aol.com/dhtml_style_guide">guidelines for keyboard shortcuts</a>. +</p> + +<p> +A good way to ensure discoverability of keyboard shortcuts +is to list them somewhere. +Your extension’s +<a href="options.html">Options page</a> +might be a good place to do this. +</p> + +<p> +For the example toolbar, +a simple JavaScript keyboard handler could look like the following. +Note how the ARIA property <code>aria-activedescendant</code> +is updated in response to user input +to reflect the current active toolbar button. +</p> + +<pre> +<head> +<script> + function optionKeyEvent(event) { + var tb = event.target; + var buttonid; + + ENTER_KEYCODE = 13; + RIGHT_KEYCODE = 39; + LEFT_KEYCODE = 37; + // Partial sample code for processing arrow keys. + if (event.type == "keydown") { + // Implement circular keyboard navigation within the toolbar buttons + if (event.keyCode == ENTER_KEYCODE) { + ExecuteButtonAction(getCurrentButtonID()); + <em>// getCurrentButtonID defined elsewhere </em> + } else if (event.keyCode == event.RIGHT_KEYCODE) { + // Change the active toolbar button to the one to the right (circular). + var buttonid = getNextButtonID(); + <em>// getNextButtonID defined elsewhere </em> + tb.setAttribute("aria-activedescendant", buttonid); + } else if (event.keyCode == event.LEFT_KEYCODE) { + // Change the active toolbar button to the one to the left (circular). + var buttonid = getPrevButtonID(); + <em>// getPrevButtonID defined elsewhere </em> + tb.setAttribute("aria-activedescendant", buttonid); + } else { + return true; + } + return false; + } +} +</script> + +<div role="toolbar" tabindex="0" aria-activedescendant="button1" id="tb1" + onkeydown="return optionKeyEvent(event);" + onkeypress="return optionKeyEvent(event);"> + <img src="buttoncut" role="button" alt="cut" id="button1"> + <img src="buttoncopy" role="button" alt="copy" id="button1"> + <img src="buttonpaste" role="button" alt="paste" id="button1"> +</div> +</pre> + + +<h2 id="more"> Provide accessible content </h2> + + +<p> +The remaining guidelines might be familiar +because they reflect good practices for all web content, +not just extensions. +</p> + +<h3 id="text">Text</h3> + +<p> +Evaluate your use of text in your extension. +Many people might find it helpful +if you provide a way to increase the text size within your extension. +If you are using keyboard shortcuts, +make sure that they don't interfere with +the zoom shortcuts built into Google Chrome. +</p> + +<p> +As an indicator of the flexibility of your UI, +apply the <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-scale">200% test</a>. +If you increase the text size or page zoom 200%, +is your extension still usable? +</p> + +<p> +Also, avoid baking text into images: +users cannot modify the size of text displayed as an image, +and screenreaders cannot interpret images. +Consider using a web font instead, +such as one of the fonts collected in the +<a href="http://code.google.com/apis/webfonts/">Google Font API</a>. +Text styled in a web font is searchable, +scales to different sizes, +and is accessible to people using screen readers. +</p> + +<h3 id="colors">Colors</h3> + +<p> +Check that there is sufficient contrast between +background color and foreground/text color in your extension. +<a href="http://snook.ca/technical/colour_contrast/colour.html">This contrast checking tool</a> +checks whether your background and foreground colors +provide appropriate contrast. +If you’re developing in a Windows environment, +you can also enable High Contrast Mode +to check the contrast of your extension. +When evaluating contrast, +verify that every part of your extension that relies on +color or graphics to convey information is clearly visible. +For specific images, you can use a tool such as the +<a href="http://www.vischeck.com/vischeck/">Vischeck simulation tool</a> +to see what an image looks like in various forms of color deficiency. +</p> + +<p> +You might consider offering different color themes, +or giving the user the ability to customize the color scheme +for better contrast. +</p> + +<h3 id="sound">Sound</h3> + +<p> +If your extension relies upon sound or video to convey information, +ensure that captions or a transcript are available. +See the +<a href="http://www.dcmp.org/ciy/">Described and Captioned Media Program guidelines</a> +for more information on captions. +</p> + +<h3 id="images">Images</h3> + +<p> +Provide informative alt text for your images. +For example: +</p> + +<pre> +<img src="img.jpg" alt="The logo for the extension"> +</pre> + +<p> +Use the alt text to state the purpose of the image +rather than as a literal description of the contents of an image. +Spacer images or purely decorative images +should have blank ("") alt text +or be removed from the HTML entirely and placed in the CSS. +</p> + +<p> +If you must use text in an image, +include the image text in the alt text. +A good resource to refer to is the +<a href="http://www.webaim.org/techniques/alttext/">WebAIM article on appropriate alt text</a>. + +<h2 id="examples">Examples</h2> + +<p> +For an example that implements keyboard navigation and ARIA properties, see +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news_a11y/">examples/extensions/news_a11y</a> +(compare it to +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/">examples/extensions/news</a>). +For more examples and for help in viewing the source code, +see <a href="samples.html">Samples</a>.
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/about_apps.html b/chrome/common/extensions/docs/templates/articles/about_apps.html new file mode 100644 index 0000000..cb83f78 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/about_apps.html @@ -0,0 +1,118 @@ +<meta name="doc-family" content="apps"> +<h1>What Are Packaged Apps?</h1> + + +<p> +Packaged apps deliver an experience as capable as a native app, +but as safe as a web page. +Just like web apps, +packaged apps are written in HTML5, JavaScript, and CSS. +But packaged apps look and behave like native apps, +and they have native-like capabilities +that are much more powerful than those available to web apps. +</p> + +<p> +<iframe title="YouTube video player" width="610" height="380" src="http://www.youtube.com/embed/lBUGTVIJVfM" frameborder="0" allowfullscreen></iframe> +</p> + +<p> +Packaged apps have access to Chrome APIs and services not available to +traditional web sites. You can build powerful apps that interact with network +and hardware devices, media tools, and much more. Here's a short list of +examples: +</p> + +<ul> + <li>Shells (VMWare, Citrix, SSH, RDP or VNC clients)</li> + <li>Music/video streaming</li> + <li>Photo/video/music editing</li> +</ul> + +<p> +Watch the <a href="http://www.youtube.com/watch?v=j8oFAr1YR-0">Chrome Apps +Google I/O presentation</a> for an in-depth introduction. +</p> + +<h2 id="look">How they look</h2> + +<p> +When a user opens a packaged app, +their focus is specifically on the tasks +relating to the app. +Packaged apps have no traditional chrome: +the omnibox (address bar), tab strip, +and other browser interface elements no longer appear. +Like native apps, they don’t live within the browser. +When launched, packaged apps can open in windows +that look like this (and you can style +your windows in all different ways): +</p> +<br> + +<img src="{{static}}/images/editor.png" + width="770" + height="586" + alt="Text editor packaged app in a standalone window"> + +<h2 id="behave">How they behave</h2> + +<p> +Packaged app pages always load locally. +This allows apps to be less dependent on the network. +Once a user installs an app, they have full control over the app's lifecycle. +Apps open and close quickly, +and the system can shut apps down at any time to improve performance. +Users can fully uninstall apps. +</p> + +<p> +Without any effort on your part, your apps will launch offline. +But you will need to put some effort into making sure user data is stored locally while offline +and then synced back up to your data server once online +(see <a href="offline_apps.html">Offline First</a>). +</p> + +<h2 id="develop">How to develop them</h2> + +<p> +Packaged apps are modified web apps. +You use the same code, frameworks, and tools of the web platform to write your apps. +Some browser features have been removed, other web APIs have been disabled +or changed to improve security and programming practices. +</p> + +<p> +New features have been added to help you build more native-like apps. +The app container and programming models control how packaged apps look and behave. +These models aim to provide users with a more native experience. +Powerful APIs have been added so your apps can have native-like capabilities, +and a serious security model is enforced to make sure these APIs are not abused.</p> + +<p> +To learn more about how to develop packaged apps: +</p> + +<ul> + <li> + <a href="app_architecture.html">Understanding the Architecture</a> + introduces the app container, programming, and security models. + </li> + <li> + <a href="app_lifecycle.html">The Fundamentals</a> + shows how to use this architecture and how to build + for offline, manage data, and embed external content. + </li> + <li> + <a href="app_network.html">Advanced Technologies</a> + shows how to use the powerful network and hardware APIs, + and how to connect your app to other apps using web intents. + </li> + <li> + <a href="app_deprecated.html">Disabled Features</a> + describes the web features that have been disabled + and what to use in their place, where relevant. + </li> +</ul> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/api_index.html b/chrome/common/extensions/docs/templates/articles/api_index.html new file mode 100644 index 0000000..3b1f7b9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/api_index.html @@ -0,0 +1,59 @@ +<h1 class="page_title">chrome.* APIs</h1> +{{?is_apps}} +<p class="doc-family apps"> +Chrome provides many special-purpose APIs like +<code>chrome.runtime</code> and <code>chrome.alarms</code> +to packaged apps. +</p> +{{:is_apps}} +<p class="doc-family extensions"> +Chrome provides APIs such as +<code>chrome.bookmarks</code> and <code>chrome.tab</code> +so that extensions can interact with the browser. +</p> +{{/is_apps}} + +<h2 id="supported">Supported APIs</h2> + +<p> +Here are the supported chrome.* APIs: +</p> + +<ul> + {{?is_apps}} + {{#api_list.apps.chrome}} + <li><a href="{{name}}.html">{{name}}</a></li> + {{/}} + {{:is_apps}} + {{#api_list.extensions.chrome}} + <li><a href="{{name}}.html">{{name}}</a></li> + {{/}} + {{/is_apps}} +</ul> + +<h2 id="experimental">Experimental APIs</h2> + +<p> +Chrome also has +<a href="experimental.html">experimental APIs</a>, +some of which will become supported APIs +in future releases of Chrome. +</p> + +<h2 id="conventions">API conventions</h2> + +<p> +Unless the doc says otherwise, +methods in the chrome.* APIs are <b>asynchronous</b>: +they return immediately, +without waiting for the operation to finish. +If you need to know the outcome of an operation, +then you pass a callback function into the method. +For more information, watch this video: +</p> + +{{^is_apps}} +<p class="doc-family extensions"> +<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/bmxr75CV36A?rel=0" frameborder="0" allowfullscreen></iframe> +</p> +{{/is_apps}} diff --git a/chrome/common/extensions/docs/templates/articles/api_other.html b/chrome/common/extensions/docs/templates/articles/api_other.html new file mode 100644 index 0000000..7fc08eee --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/api_other.html @@ -0,0 +1,87 @@ +<h1>Other APIs</h1> + +<p> +In addition to the +<a href="api_index.html">chrome.* APIs</a>, +extensions can use all the APIs +that the browser provides +to web pages and apps. +If the browser doesn't support an API you want to use, +you can bundle additional API libraries into your extension. +</p> + +<p>Here's a sampling of the APIs that extensions can use:</p> + +<dl> +<dt><strong> Standard JavaScript APIs </strong></dt> +<dd> These are the same core JavaScript and + <a href="https://developer.mozilla.org/en/Gecko_DOM_Reference">Document Object Model</a> + (DOM) APIs + that you can use in ordinary web apps. + +<!-- Use onclick in your toolbar div to add click behavior. +E.g. window.open(someUrl). --></dd> +<dt><strong> XMLHttpRequest </strong></dt> +<dd> + Use <a href="xhr.html">XMLHttpRequest</a> + to request data from one or more servers. + The <a href="manifest.html#permissions">permissions</a> field + of the manifest specifies + which hosts the extension can send requests to. + </dd> +<dt> <strong>HTML5 and other emerging APIs</strong></dt> +<dd> Google Chrome supports HTML5 features, + along with other emerging APIs. + Here are some of the APIs you can use: + <ul> + <li> audio + (<a href="http://www.html5rocks.com/tutorials/audio/quick/">tutorial</a>) </li> + <li> application cache + (<a href="http://www.html5rocks.com/tutorials/appcache/beginner/">tutorial</a>) </li> + <li> canvas + (<a href="http://www.html5rocks.com/en/tutorials/#canvas">articles</a>) </li> + <li> geolocation + (<a href="http://www.html5rocks.com/tutorials/geolocation/trip_meter/">tutorial</a>) </li> + <li> local storage + (<a href="http://www.html5rocks.com/en/tutorials/offline/storage/">tutorial</a>) </li> + <li> notifications + (<a href="http://www.html5rocks.com/tutorials/notifications/quick/">tutorial</a>) </li> + <li> video + (<a href="http://www.html5rocks.com/en/tutorials/video/basics/">tutorial</a>) </li> + <li> web database + (<a href="http://www.html5rocks.com/tutorials/webdatabase/todo/">tutorial</a>) </li> + </ul> + <p> + See <a href="http://www.html5rocks.com">html5rocks.com</a> + for HTML5 information, tutorials, an interactive playground, + and links to other resources. + </p> +</dd> + +<dt><strong> WebKit APIs </strong></dt> +<dd> + Because Google Chrome is built upon WebKit, + your extensions can use WebKit APIs. + Especially useful are the experimental CSS features + such as filters, animations, and transformations. + Here's an example of using WebKit styles + to make the UI spin: + <pre><style> + div:hover { + -webkit-transform: rotate(360deg); + -webkit-transition: all 1s ease-out; + } +</style> +</pre> + +</dd> +<dt><strong> V8 APIs</strong>, such as<strong> JSON </strong></dt> +<dd> Because JSON is in V8, you don't need to include a JSON library to use JSON functions. </dd> +<dt><strong>APIs in bundled libraries</strong></dt> +<dd> If you want to use a library that the browser doesn't provide +(for example, jQuery), +you can bundle that library's JavaScript files with your extension. +Bundled libraries work in extensions +just as they do in other web pages. +</dd> +</dl>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_architecture.html b/chrome/common/extensions/docs/templates/articles/app_architecture.html new file mode 100644 index 0000000..6a6cdc4 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_architecture.html @@ -0,0 +1,173 @@ +<meta name="doc-family" content="apps"> +<h1>Understand the Architecture</h1> + + +<p> +Packaged apps integrate closely with a user’s operating system. +They are designed to be run outside of a browser tab, +to run robustly in offline and poor connectivity scenarios and +to have far more powerful capabilities than are available +in a typical web browsing environment. +The app container, programming, and security models +support these packaged app requirements. +</p> + +<h2 id="container">App container model</h2> + +<p> +The app container describes the visual appearance +and loading behavior of packaged apps. +Packaged apps look different than traditional web apps +because the app container does not show any traditional web page UI controls; +it simply contains a blank rectangular area. +This allows an app to blend with “native” apps on the system, +and it prevents the user from “messing” with the app logic +by manually changing the URL. +</p> + +<p> +Packaged apps are loaded differently than web apps. +Both load the same type of content: +HTML documents with CSS and JavaScript; +however, a packaged app is loaded in the app container, +not in the browser tab. +Also, the app container must load the main document +of the packaged app from a local source. +This forces all packaged apps to be at least minimally functional +when offline and it provides a place +to enforce stricter security measures. +</p> + +<img src="{{static}}/images/container.png" + width="671" + height="172" + alt="how app container model works"> + + +<h2 id="programming">Programming model</h2> + +<p> +The programming model describes the lifecycle +and window behavior of packaged apps. +Similar to native apps, +the goal of this programming model is to give users +and their systems full control over the app lifecycle. +The packaged app lifecycle should be independent +of browser window behavior or a network connection. +</p> + +<p> +The “event page” manages the packaged app lifecycle +by responding to user gestures and system events. +This page is invisible, only exists in the background, +and can be closed automatically by the system runtime. +It controls how windows open and close and +when the app is started or terminated. +There can only be one “event page” for a packaged app. +<p> + +<p> +<iframe title="YouTube video player" width="610" height="380" src="http://www.youtube.com/embed/yr1jgREbH8U" frameborder="0" allowfullscreen></iframe> +</p> + +<h3>App lifecycle at a glance</h3> + +<p> +For detailed instructions on how to use the programming model, +see <a href="app_lifecycle.html">Manage App Lifecycle</a>. +Here's a brief summary of the packaged app lifecyle +to get you started: +</p> + +<br> + +<table border="0"> + <tr> + <th scope="col"> Stage </th> + <th scope="col"> Summary </th> + </tr> + <tr> + <td>Installation</td> + <td>User chooses to install the app and explicitly accepts the + <a href="manifest.html#permissions">permissions</a>. + </td> + </tr> + <tr> + <td>Startup</td> + <td>The event page is loaded, + the 'launch' event fires, + and app pages open in windows. + You + <a href="app_lifecycle.html#eventpage">create the windows</a> + that your app requires, + how they look, and how they communicate + with the event page and with other windows. + </td> + </tr> + <tr> + <td>Termination</td> + <td>User can terminate apps at any time + and app can be quickly restored to previous state. + <a href="app_lifecycle.html#H3-7">Stashing data</a> + protects against data loss.</td> + </tr> + <tr> + <td>Update</td> + <td>Apps can be updated at any time; + however, the code that a packaged app is running + cannot change during a startup/termination cycle.</td> + </tr> + <tr> + <td>Uninstallation</td> + <td>User can actively uninstall apps. + When uninstalled, no executing code or + private data is left behind.</td> + </tr> +</table> + +<h2 id="security">Security model</h2> + +<p> +The packaged apps security model protects users +by ensuring their information is managed +in a safe and secure manner. +<a href="app_csp.html">Comply with CSP</a> +includes detailed information on how to comply with content security policy. +This policy blocks dangerous scripting +reducing cross-site scripting bugs +and protecting users against man-in-the-middle attacks. +</p> + +<p> +Loading the packaged app main page locally provides a place +to enforce stricter security than the web. +Like Chrome extensions, +users must explicitly agree to trust the packaged app on install; +they grant the app permission to access and use their data. +Each API that your app uses will have its own permission. +The packaged apps security model also provides the ability +to set up privilege separation on a per window basis. +This allows you to minimize the code in your app +that has access to dangerous APIs, +while still getting to use them. +</p> + +<p> +Packaged apps reuse Chrome extension process isolation, +and take this a step further by isolating storage and external content. +Each app has its own private storage area +and can’t access the storage of another app +or personal data (such as cookies) for websites that you use in your browser. +All external processes are isolated from the app. +Since iframes run in the same process as the surrounding page, +they can only be used to load other app pages. +You can use the <code>object</code> tag to +<a href="app_external.html">embed external content</a>; +this content runs in a separate process from the app. +</p> + +<p> +<iframe title="YouTube video player" width="610" height="380" src="http://www.youtube.com/embed/EDtiWN42lHs" frameborder="0" allowfullscreen></iframe> +</p> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_csp.html b/chrome/common/extensions/docs/templates/articles/app_csp.html new file mode 100644 index 0000000..3af785c --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_csp.html @@ -0,0 +1,126 @@ +<h1>Comply with CSP</h1> + + +<p> +If you're unfamiliar with Content Security Policy (CSP), +<a href="http://www.html5rocks.com/en/tutorials/security/content-security-policy/">An Introduction to Content Security Policy</a> +is a good starting point. +It covers the broader web platform view of CSP; +packaged apps CSP isn't as flexible. +You should read the +<a href="http://code.google.com/chrome/extensions/contentSecurityPolicy.html">Chrome extension Content Security Policy</a> +as it's the foundation for the packaged app CSP. +For brevity's sake, +we don't repeat the same information here. +</p> + +<p> +CSP is a policy to mitigate against cross-site scripting issues, +and we all know that cross-scripting is bad. +We aren’t going to try and convince you +that CSP is a warm-and-fuzzy new policy. +There's work involved; +you'll need to learn how to do fundamental tasks differently. +</p> + +<p> +The purpose of this doc is to tell you +exactly what the CSP policy is for packaged apps, +what you need to do to comply with it, +and how you can still do those fundamental tasks +in a way that is CSP–compliant. +</p> + +<h2 id="what">What is the CSP for packaged apps?</h2> + +<p>The content security policy for packaged apps restricts +you from doing the following:</p> + +<ul> + <li>You can’t use inline scripting in your packaged app pages. + The restriction bans both <script> blocks and + event handlers (<button onclick=”...”>).</li> + <li>You can’t reference any external resources in any of your app files + (except for video and audio resources). + You can’t embed external resources in an iframe.</li> + <li>You can’t use string-to-JavaScript methods like + <code>eval()</code> and <code>function()</code>.</li> +</ul> + +<p>This is implemented via the following policy value:</p> + +<pre> +default-src 'self'; +connect-src *; +style-src 'self' data: chrome-extension-resource: 'unsafe-inline'; +img-src 'self' data: chrome-extension-resource:; +frame-src 'self' data: chrome-extension-resource:; +font-src 'self' data: chrome-extension-resource:; +media-src *; +</pre> + +<p> +Your packaged app can only refer to scripts and objects +within your app, with the exception of media files +(apps can refer to video and audio outside the package). +Chrome extensions will let you relax the default Content Security Policy; +packaged apps won’t. +</p> + +<h2 id="how">How to comply with CSP</h2> + +<p> +All JavaScript and all resources should be local +(everything gets packaged in your packaged app). +</p> + +<h2 id="but">"But then how do I..."</h2> + +<p> +It's very possible that you are using templating libraries +and many of these won’t work with CSP. +You may also want to access external resources in your app +(external images, content from websites). +</p> + +<h3>Use templating libraries</h3> + +<p> +Use a library that offers precompiled templates +and you’re all set. +You can still use a library that doesn’t offer precompilation, +but it will require some work on your part and there are restrictions. +</p> + +<p> +You will need to use sandboxing to isolate any content +that you want to do ‘eval’ things to. +Sandboxing lifts CSP on the content that you specify. +If you want to use the very powerful Chrome APIs in your packaged app, +your sandboxed content can't directly interact with these APIs +(see <a href="app_external.html#sandboxing">Sandbox local content</a>). +</p> + +<h3>Access remote resources</h3> + +<p> +You can fetch remote resources via <code>XMLHttpRequest</code> +and serve them via <code>blob:</code>, <code>data:</code>, +or <code>filesystem:</code> URLs +(see <a href="app_external.html#external">Referencing external resources</a>). +</p> + +<p> +Video and audio can be loaded from remote services +because they have good fallback behavior when offline or under spotty connectivity. +</p> + +<h3>Embed web content</h3> + +<p> +Instead of using an iframe, +you can call out to an external URL using an object tag +(see <a href="app_external.html#objecttag">Embed external web pages</a>). +</p> + +<p class="backtotop"><a href="#top">Back to top</a></p> diff --git a/chrome/common/extensions/docs/templates/articles/app_deprecated.html b/chrome/common/extensions/docs/templates/articles/app_deprecated.html new file mode 100644 index 0000000..ea8a66a --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_deprecated.html @@ -0,0 +1,99 @@ +<h1>Disabled Web Features</h1> +<!-- --> + +<p> +Though packaged apps use the web platform, +some web features have been disabled +or else are used in a different way. +Mainly this is to avoid security issues and +to improve programming practices. +Below is a summary of the disabled features +of the web platform +and potential work-arounds: +</p> + +<table border="0"> + <tr> + <th scope="col"> Disabled </th> + <th scope="col"> Work-around </th> + </tr> + <tr> + <td><code>alert</code></td> + <td>Use a custom lightbox/popup.</td> + </tr> + <tr> + <td>Browser chrome APIs</td> + <td>N/A.</td> + </tr> + <tr> + <td><code>confirm</code></td> + <td>Use a custom lightbox/popup.</td> + </tr> + <tr> + <td><code>document.cookie</code></td> + <td>Packaged app pages are not rendered on the server, so there is no need to use these.</td> + </tr> + <tr> + <td><code>document.close</code></td> + <td>N/A.</td> + </tr> + <tr> + <td><code>document.open</code></td> + <td>N/A.</td> + </tr> + <tr> + <td><code>document.write</code></td> + <td>Use document.createElement.</td> + </tr> + <tr> + <td>External resources</td> + <td>Use the <code>object</code> tag for iframes + See <a href="app_external.html">Embed Content</a>. + Video and audio are allowed to have non-local URLs.</td> + </tr> + <tr> + <td>Flash</td> + <td>Use HTML5 Platform.</td> + </tr> + <tr> + <td>Form submission</td> + <td>Use JavaScript to process form content + (listen for submit event, process data locally first + before sending to server).</td> + </tr> + <tr> + <td>javascript: urls</td> + <td>You cannot use bookmarklets for inline javascript on anchors. + Use the traditional click handler instead.</td> + </tr> + <tr> + <td>localStorage</td> + <td>Use IndexedDB or the Storage API (which also syncs to the cloud).</td> + </tr> + <tr> + <td>Navigation</td> + <td>Links open up with the system web browser. + <code>window.history</code> and <code>window.location</code> + are disabled.</td> + </tr> + <tr> + <td>Non-sandboxed plugins</td> + <td>N/A.</td> + </tr> + <tr> + <td><code>showModalDialog</code></td> + <td>Use a custom lightbox/popup.</td> + </tr> + <tr> + <td>Synchronous <code>XMLHttpRequest</code></td> + <td>Use async-only <code>XMLHttpRequest</code>: + <a href="http://updates.html5rocks.com/2012/01/Getting-Rid-of-Synchronous-XHRs">Getting Rid of Synchrounous XXRs</a>.</td> + </tr> + <tr> + <td>webSql</td> + <td>Use IndexedDB or + <a href="app_storage.html">Filesystem API</a>.</td> + </tr> +</table> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_external.html b/chrome/common/extensions/docs/templates/articles/app_external.html new file mode 100644 index 0000000..663f7b1 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_external.html @@ -0,0 +1,281 @@ +<h1>Embed Content</h1> + + +<p> +The <a href="app_architecture.html#security">packaged apps security model</a> disallows +external content in iframes and +the use of inline scripting and <code>eval()</code>. +You can override these restrictions, +but your external content must be isolated from the app. +</p> + +<p> +Isolated content cannot directly +access the app's data or any of the APIs. +Use cross-origin XMLHttpRequests +and post-messaging to communicate between the event page and sandboxed content +and indirectly access the APIs. +</p> + +<p class="note"> +<b>API Sample: </b> +Want to play with the code? +Check out the +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/sandbox">sandbox</a> sample. +</p> + +<h2 id="external">Referencing external resources</h2> + +<p> +The <a href="app_csp.html">Content Security Policy</a> used by apps disallows +the use of many kinds of remote URLs, so you can't directly reference external +images, stylesheets, or fonts from an app page. Instead, you can use use +cross-origin XMLHttpRequests to fetch these resources, +and then serve them via <code>blob:</code> URLs. +</p> + +<h3>Manifest requirement</h3> + +<p> +To be able to do cross-origin XMLHttpRequests, you'll need to add a permission +for the remote URL's host: +</p> + +<pre> +"permissions": [ + "...", + "https://supersweetdomainbutnotcspfriendly.com/" + ] +</pre> + +<h3>Cross-origin XMLHttpRequest</h3> + +<p> +Fetch the remote URL into the app and serve its contents as a <code>blob:</code> +URL: +</p> + +<pre> +var xhr = new XMLHttpRequest(); +xhr.open('GET', 'https://supersweetdomainbutnotcspfriendly.com/image.png', true); +xhr.responseType = 'blob'; +xhr.onload = function(e) { + var img = document.createElement('img'); + img.src = window.webkitURL.createObjectURL(this.response); + document.body.appendChild(img); +}; + +xhr.send(); +</pre> + +<p>You may want to <a href="offline_apps.html#saving-locally">save</a> +these resources locally, so that they are available offline.</p> + +<h2 id="browsertag">Embed external web pages</h2> + +<p class="note"> +<b>API Sample: </b> +Want to play with the code? Check out the +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/browser-tag">browser-tag</a> +sample. +</p> + +<p> +The <code>browser</code> tag allows you to embed external web content in your +app, for example, a web page. It replaces iframes that point to remote URLs, +which are disabled inside packaged apps. Unlike iframes, the +<code>browser</code> tag runs in a separate process. This means that an exploit +inside of it will still be isolated and won't be able to gain elevated +privileges. Further, since its storage (cookies, etc.) is isolated from the app, +there is no way for the web content to access any of the app's data. +</p> + +<h3>Add browser element</h3> + +<p> +Your <code>browser</code> element must include the URL to the source content +and specify its dimensions. +</p> + +<pre><browser src="http://news.google.com/" width="640" height="480"></browser></pre> + +<h3>Update properties</h3> + +<p> +To dynamically change the <code>src</code>, <code>width</code> and +<code>height</code> properties of a <code>browser</code> tag, you can either +set those properties directly on the JavaScript object, or use the +<code>setAttribute</code> DOM function. +</p> + +<pre> +document.querySelector('#mybrowser').src = + 'http://blog.chromium.org/'; +// or +document.querySelector('#mybrowser').setAttribute( + 'src', 'http://blog.chromium.org/'); +</pre> + +<h2 id="sandboxing">Sandbox local content</h2> + +<p> +Sandboxing allows specified pages +to be served in a sandboxed, unique origin. +These pages are then exempt from their Content Security Policy. +Sandboxed pages can use iframes, inline scripting, +and <code>eval()</code>. +Check out the manifest field description for +<a href="manifest.html#sandbox">sandbox</a>. +</p> + +<p> +It's a trade-off though: +sandboxed pages can't use the chrome.* APIs. +If you need to do things like <code>eval()</code>, +go this route to be exempt from CSP, +but you won't be able to use the cool new stuff. +</p> + +<h3>Use inline scripts in sandbox</h3> + +<p> +Here's a sample sandboxed page +which uses an inline script and <code>eval()</code>: +</p> + +<pre> +<html> + <body> + <h1>Woot</h1> + <script> + document.write('I am an inline script.<br>'); + eval('document.write(\'I am an eval-ed inline script.\');'); + </script> + </body> +</html> +</pre> + +<h3>Include sandbox in manifest</h3> + +<p> +You need to include the <code>sandbox</code> field in the manifest +and list the app pages to be served in a sandbox: +</p> + +<pre> +"sandbox": { + "pages": ["sandboxed.html"] +} +</pre> + +<h3>Opening a sandboxed page in a window</h3> + +<p> +Just like any other app pages, +you can create a window that the sandboxed page opens in. +Here's a sample that creates two windows, +one for the main app window that isn't sandboxed, +and one for the sandboxed page: +</p> + +<pre> +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('window.html', { + 'width': 400, + 'height': 400, + 'left': 0, + 'top': 0 + }); + + chrome.app.window.create('sandboxed.html', { + 'width': 400, + 'height': 400, + 'left': 400, + 'top': 0 + }); +}); +</pre> + +<h3>Embedding a sandboxed page in an app page</h3> + +<p>Sandboxed pages can also be embedded within another app page + using an <code>iframe</code>:</p> + +<pre> +<!DOCTYPE html> +<html> +<head> +</head> + <body> + <p>I am normal app window.</p> + + <iframe src="sandboxed.html" width="300" height="200"></iframe> + </body> +</html> +</pre> + + +<h2 id="postMessage">Sending messages to sandboxed pages</h2> + +<p> +There are two parts to sending a message: +you need to post a message from the sender page/window, +and listen for messages on the receiving page/window. +</p> + +<h3>Post message</h3> + +<p> +You can use <code>postMessage</code> to communicate +between your app and sandboxed content. +Here's a sample background script +that posts a message to the sandboxed page it +opens: +</p> + +<pre> +var myWin = null; + +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('sandboxed.html', { + 'width': 400, + 'height': 400 + }, function(win) { + myWin = win; + myWin.postMessage('Just wanted to say hey.', '*'); + }); +}); +</pre> + +<p> +Generally speaking on the web, +you want to specify the exact origin +from where the message is sent. +Packaged apps have no access +to the unique origin of sandboxed content, +so you can only whitelist all origins +as acceptable origins ('*'). +On the receiving end, +you generally want to check the origin; +but since packaged apps content is contained, +it isn't necessary. +To find out more, +see <a href="https://developer.mozilla.org/en/DOM/window.postMessage">window.postMessage</a>. +</p> + +<h3>Listen for message</h3> + +<p> +Here's a sample message receiver +that gets added to your sandboxed page: +</p> + +<pre> +var messageHandler = function(e) { + console.log('Background script says hello.', e.data); +}; + +window.addEventListener('message', messageHandler); +</pre> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_frameworks.html b/chrome/common/extensions/docs/templates/articles/app_frameworks.html new file mode 100644 index 0000000..5c829f3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_frameworks.html @@ -0,0 +1,329 @@ +<h1>MVC Architecture</h1> + + +<p> +As modern browsers become more powerful with rich features, +building full-blown web applications in JavaScript is not only feasible, +but increasingly popular. +Based on +<a href="http://httparchive.org/trends.php?s=intersection&minlabel=Jan+20+2011&maxlabel=Jan+15+2012">trends</a> +on <a href="http://httparchive.org/">HTTP Archive</a>, +deployed JavaScript code size has grown 45% over the course of the year. +</p> + +<img src="{{static}}/images/jstransferrequests.png" + width="568" + height="292" + alt="JS transfer size and JS requests"> + +<p> +With JavaScript's popularity climbing, +our client-side applications are much more complex than before. +Application development requires collaboration from multiple developers. +Writing <strong>maintainable</strong> and +<strong>reusable</strong> code is crucial in the new web app era. +The Chrome packaged app, with its rich client-side features, is no exception. +</p> + +<p> +Design patterns are important to write maintainable and reusable code. +A pattern is a reusable solution that can be applied to commonly occurring problems in software design — +in our case — writing Chrome packaged apps. +We recommend that developers decouple the app +into a series of independent components following the MVC pattern. +</p> + +<p> +In the last few years, +a series of JavaScript MVC frameworks have been developed, +such as <a href="http://backbonejs.org/">backbone.js</a>, <a href="http://emberjs.com/">ember.js</a>, <a href="http://angularjs.org/">AngularJS</a>, <a href="http://sencha.com/">Sencha</a>, <a href="http://kendo.com/">Kendo UI</a>, and more. +While they all have their unique advantages, each one of them follows some form of MVC pattern +with the goal of encouraging developers to write more structured JavaScript code. +</p> + +<h2 id="mvc">MVC pattern overview</h2> + +<p> +MVC offers architectural benefits over standard JavaScript — +it helps you write better organized, and therefore more maintainable code. +This pattern has been used and extensively tested +over multiple languages and generations of programmers. +</p> + +<p> +MVC is composed of three components: +</p> + +<img src="{{static}}/images/mvc.png" + width="466" + height="303" + alt="model-view-controller"> + +<h3>Model</h3> + +<p> +Model is where the application’s data objects are stored. +The model doesn’t know anything about views and controllers. +When a model changes, typically it will notify its observers that a change has occurred. +</p> + +<p> +To understand this further, let’s use the Todo list app, a simple, one page web app that tracks your task list. +</p> + +<br> + +<img src="{{static}}/images/todos.png" + width="444" + height="366" + alt="model-view-controller"> + +<p> +The model here represents attributes associated +with each todo item such as description and status. +When a new todo item is created, +it is stored in an instance of the model. +</p> + +<h3>View</h3> + +<p> +View is what's presented to the users and how users interact with the app. +The view is made with HTML, CSS, JavaScript and often templates. +This part of your Chrome packaged app has access to the DOM. +</p> + +<p> +For example, in the above todo list web app, +you can create a view that nicely presents the list of todo items to your users. +Users can also enter a new todo item through some input format; +however, the view doesn’t know how to update the model because that’s the controller’s job. +</p> + +<h3>Controller</h3> + +<p> +The controller is the decision maker and the glue between the model and view. +The controller updates the view when the model changes. +It also adds event listeners to the view and +updates the model when the user manipulates the view. +</p> + +<p> +In the todo list web app, +when the user checks an item as completed, +the click is forwarded to the controller. +The controller modifies the model to mark item as completed. +If the data needs to be persistent, it also makes an async save to the server. +In rich client-side web app development such as Chrome packaged apps, +keeping the data persistent in local storage is also crucial. +In this case, the controller also handles saving the data +to the client-side storage such as <a href="app_storage.html">FileSystem API</a>. +</p> + +<p> +There are a few variations of the MVC design pattern +such as MVP (Model–View–Presenter) +and MVVP(Model–View–ViewModel). +Even with the so called MVC design pattern itself, +there is some variation between the traditional MVC pattern +vs the modern interpretation in various programming languages. +For example, some MVC–based frameworks will have +the view observe the changes in the models +while others will let the controller handle the view update. +This article is not focused on the comparison of various implementations +but rather on the separation–of–concerns and +it's importance in writing modern web apps. +</p> + +<p> +If you are interested in learning more, +we recommend <a href="https://plus.google.com/u/0/115133653231679625609/posts">Addy Osmani's</a> online book: <a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/">Learning JavaScript Design Patterns</a>. +</p> + +<p> +To summarize, the MVC pattern brings modularity +to application developers and it enables: +</p> + +<ul> + <li>Reusable and extendable code.</li> + <li>Separation of view logic from business logic.</li> + <li>Allow simultaneous work between developers who are responsible + for different components (such as UI layer and core logic).</li> + <li>Easier to maintain.</li> +</ul> + +<h2 id="mvcpersistence">MVC persistence patterns</h2> + +<p> +There are many different ways of implementing persistence +with an MVC framework, each with different trade–offs. +When writing Chrome packaged apps, +choose the frameworks with MVC and persistence patterns +that feel natural to you and fit you application needs. +</p> + +<h3>Model does its own persistence - ActiveRecord pattern</h3> + +<p> +Popular in both server–side frameworks like Ruby on Rails, +and client-side frameworks like +<a href="http://backbonejs.org">Backbone.js</a> and +<a href="http://emberjs.com/">ember.js</a>, +the ActiveRecord pattern places the responsibility +for persistence on the model itself +and is typically implemented via JSON API. +</p> + +<p> +A slightly different take from +having a model handle the persistence +is to introduce a separate concept of Store and Adapter API. +Store, Model and +Adapter (in some frameworks it is called Proxy) +work hand by hand. +Store is the repository that holds the loaded models, +and it also provides functions such as creating, +querying and filtering the model instances contained within it. +</p> + +<p> +An adapter, or a proxy, receives the requests from a store and +translates them into appropriate actions to take +against your persistent data layer +(such as JSON API). +This is interesting in the modern web app design +because you often interact with more than one persistent data layer +such as a remote server and browser’s local storage. +Chrome package apps provides both +<a href="storage.html">Chrome Storage API</a> and +<a href="fileSystem.html">HTML 5 fileSystem API</a> for client side storage. +</p> + +<p>Pros:</p> + +<ul> + <li>Simple to use and understand.</li> +</ul> + +<p> +Cons: +</p> + +<ul> + <li>Hard to test since the persistence layer is ‘baked’ into the object hierarchy.</li> + <li>Having different objects use different persistent stores is difficult + (for example, FileSystem APIs vs indexedDB vs server–side).</li> + <li>Reusing Model in other applications may create conflicts, + such as sharing a single Customer class between two different views, + each view wanting to save to different places.</li> +</ul> + +<h3>Controller does persistence</h3> + +<p> +In this pattern, the controller holds a reference +to both the model and a datastore +and is responsible for keeping the model persisted. +The controller responds to lifecycle events like Load, Save, Delete, +and issues commands to the datastore to fetch or update the model. +</p> + +<p> +Pros: +</p> + +<ul> + <li>Easier to test, controller can be passed a mock datastore to write tests against.</li> + <li>The same model can be reused with multiple datastores just by constructing controllers with different datastores.</li> +</ul> + +<p> +Cons: +</p> + +<ul> + <li>Code can be more complex to maintain.</li> +</ul> + +<h3>AppController does persistence</h3> + +<p> +In some patterns, there is a supervising controller responsible +for navigating between one MVC and another. +The AppController decides, for example, +that a ‘Back’ button moves the client from an editing screen +(which contains MVC widgets/formats), +to a settings screen. +</p> + +<p> +In the AppController pattern, +the AppController responds to events +and changes the app’s current screen by issuing a call +to the datastore to load any models needed and +constructing all of the matching views and controllers for that screen. +</p> + +<p> +Pros: +</p> + +<ul> + <li>Moves persistence layer even higher up the stack where it can be easily changed.</li> + <li>Doesn’t pollute lower level controllers like a DatePickerController with the need to know about persistence.</li> + <li>Aligns nicely with an ‘Intent’ model. + Each AppController corresponds to an intent, like “ChoosePhoto”, or “SendMessage”. + The Intent contains a reference to the model data needed (Customer#123) and + the type of CRUD operation (load, save, delete, and so on).</li> +</ul> + +<p> +Cons: +</p> + +<ul> + <li>Each ‘Page/Screen’ of the app now requires a lot of boilerplate to write or update: Model, View, Controller, AppController.</li> +</ul> + +<h3>Recommended MVC frameworks</h3> + +<p> +MVC is crucial to designing Chrome packaged apps. +We recommend the following <a href="app_csp.html">CSP–Compliant</a> MVC frameworks +for writing secure and scalable Chrome packaged apps: +</p> + +<ul> + <li><a href="http://angularjs.org/">AngularJS</a> + (<a href="https://github.com/GoogleChrome/textdrive-app">Text Drive Reference App</a>)</li> + <li><a href="http://kendo.com/">Kendo UI</a> + (<a href="https://github.com/GoogleChrome/kendo-photo-booth-app">Photo Booth Reference App</a>)</li> + <li><a href="http://www.sencha.com/">Sencha</a> + (<a href="https://github.com/GoogleChrome/sencha-video-player-app">Video Player Reference App</a>)</li> +</ul> + +<h2 id="resources">Useful resources</h2> + +<h3>Online</h3> + +<ul> + <li><a href="http://www.html5rocks.com/">HTML5Rocks.com</a></li> + <li><a href="http://addyosmani.com/resources/essentialjsdesignpatterns/book/">Learning JavaScript Design Patterns</a> + (by Addy Osmani)</li> + <li><a href="http://addyosmani.github.com/todomvc/">TodoMVC</a></li> +</ul> + +<h3>Books</h3> + +<ul> + <li><a href="http://www.amazon.com/JavaScript-Web-Applications-Alex-MacCaw/dp/144930351X">JavaScript Web Applications</a> + (By Alex MacCaw)</li> + <li><a href="http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752/ref=pd_sim_b_2">JavaScript Patterns</a> + (By Stoyan Stefonov)</li> + <li><a href="http://www.amazon.com/Maintainable-JavaScript-Nicholas-C-Zakas/dp/1449327680">Maintainable JavaScript</a> + (By Nicolas Z. Zakas)</li> +</ul> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_hardware.html b/chrome/common/extensions/docs/templates/articles/app_hardware.html new file mode 100644 index 0000000..49df9c3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_hardware.html @@ -0,0 +1,696 @@ +<h1>Accessing Hardware Devices</h1> + + +<p> +This doc shows you how packaged apps can connect to USB devices +and read from and write to a user's serial ports. +See also the reference docs for the +<a href="experimental.usb.html">USB API</a> +and the +<a href="experimental.serial.html">Serial API</a>. +The <a href="experimental.bluetooth.html">Bluetooth API</a> has just landed and +we'll write more on this soon. +We've included a link to an early sample below. +</p> + +<p class="note"> +<b>API Samples: </b> +Want to play with the code? +Check out the +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/serial">serial</a>, +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/servo">servo</a>, +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/usb">usb</a>, +and <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/bluetooth-demo">bluetooth-demo</a> samples. +</p> + +<h2 id="usb">Accessing USB devices</h2> + +<p> +You can use the USB API to send messages to any connected device. +</p> + +<h3>Manifest requirement</h3> + +<p> +You must add the "usb" permission +to the manifest file: +</p> + +<pre> +"permissions": [ + "app.window", + "experimental", + "usb" +] +</pre> + +<h3>Finding a device</h3> + +<p> +Every device in a USB bus is identified +by its vendor and product IDs. +To find a device, +use the <code>findDevice()</code> method +which has four parameters: +</p> + +<pre> +chrome.experimental.usb.findDevice(vendorId, productId, eventCallbacks, onDeviceFoundCallback) +</pre> + +<br> + +<table border="0"> + <tr> + <th scope="col"> Parameter (type) </th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>vendorId (long)</td> + <td>The vendor ID for your USB device (in Linux, use lsusb to find it).</td> + </tr> + <tr> + <td>productId (long)</td> + <td>The product ID for your USB device (in Linux, use lsusb to find it).</td> + </tr> + <tr> + <td>eventCallbacks(object)</td> + <td>An object with a single key, "onEvent", + to be called whenever an event occurs on the corresponding device. + This will be the primary method of receiving information from the device. + As the host-initiated USB protocol is complex, read on to learn more. + </td> + </tr> + <tr> + <td>onDeviceFoundCallback()</td> + <td>Called when the device is found. + The callback's parameter is an object + with three properties: <code>handle</code>, + <code>vendorId</code>, + <code>productId</code>; + or <code>NULL</code>, + if no device is found. + Save this object + as it's required to send messages to the device.</td> + </tr> +</table> + +<p> +Example: +</p> + +<pre> +var onDeviceFound = function(device) { + deviceObj=device; + if (device) { + console.log(“Device found: ”+device.handle); + } else { + console.log(“Device could not be found”); + } +}; + +var onUsbEvent = function(event) { + console.log(“USB event!”); +}; + +chrome.experimental.usb.findDevice(vendorId, productId, {"onEvent": onUsbEvent}, onDeviceFound); +</pre> + +<h3>USB transfers and receiving data from a device</h3> + +<p> +USB protocol defines four types of transfers: +control, bulk, isochronous and interrupt. +Theoretically they can all occur in both directions:<br> +device-to-host and host-to-device. +Host-to-device is initiated by your code and is described in the next sections. +</p> + +<p> +Device-to-host messages are handled by Chrome and delivered +to the <code>onEvent()</code> callback +defined in the <code>findDevice()</code> method. +For each message from the device, +the <code>onEvent</code> callback will receive +an event object with the following properties: +</p> + +<br> + +<table border="0"> + <tr> + <th scope="col"> Property </th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>type (string)</td> + <td>Currently always contains the string "transferResult".</td> + </tr> + <tr> + <td>resultCode (integer)</td> + <td>0 is success; other values indicate failure.</td> + </tr> + <tr> + <td>data (integer array)</td> + <td>Contains the data sent by the device. + </td> + </tr> +</table> + +<p> +Example: +</p> + +<pre> +var onUsbEvent = function(event) { + if (event && event.resultCode===0 && event.data) { + console.log(“got ”+event.data.length+" bytes"); + } +}; + +chrome.experimental.usb.findDevice( vendorId, productId, {"onEvent": onUsbEvent}, onDeviceFound); +</pre> + +<h3>Sending data - control transfers</h3> + +<p> +Control transfers are generally used to send configuration +or command parameters to a USB device. +The method is simple and receives three parameters: +</p> + +<pre> +chrome.experimental.usb.controlTransfer(deviceObj, transferInfo, transferCallback) +</pre> + +<br> + +<table border="0"> + <tr> + <th scope="col"> Parameter (types)</th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>deviceObj</td> + <td>Object received from <code>findDevice()</code> callback.</td> + </tr> + <tr> + <td>transferInfo</td> + <td>Parameter object with values from the table below. + Check your USB device protocol specification + to know which values are supported.</td> + </tr> + <tr> + <td>transferCallback()</td> + <td>Invoked when the transfer has completed. + Please note this only indicates that + the transfer has been processed. + The device's response, if any, will always be sent through + the <code>onEvent()</code> callback set on <code>findDevice()</code>. + </td> + </tr> +</table> + +<p> +Values for <code>transferInfo</code> object: +</p> + +<table border="0"> + <tr> + <th scope="col"> Value </th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>requestType (string)</td> + <td>"vendor", "standard", "class" or "reserved".</td> + </tr> + <tr> + <td>recipient (string)</td> + <td>"device", "interface", "endpoint" or "other".</td> + </tr> + <tr> + <td>direction (string)</td> + <td>in" or "out". + IN direction is used to notify the device + that it should send information to the host. + All communication in a USB bus is host-initiated, + so use an 'in' transfer to allow a device + to send information back.</td> + </tr> + <tr> + <td>request (integer)</td> + <td>Defined by your device's protocol.</td> + </tr> + <tr> + <td>value (integer)</td> + <td>Defined by your device's protocol.</td> + </tr> + <tr> + <td>index (integer)</td> + <td>Defined by your device's protocol.</td> + </tr> + <tr> + <td>length (integer)</td> + <td>Only used when direction is "in". + Notifies the device that this is the amount + of data the host is expecting in response.</td> + </tr> + <tr> + <td>data (integer array)</td> + <td>Defined by your device's protocol, + required when direction is "out". + <b>WARNING: </b>in the near future, + this parameter will likely change + to <code>ArrayBuffer</code>.</td> + </tr> +</table> + +<p> +Example: +</p> + +<pre> +var transferInfo = { + "requestType": "vendor", + "recipient": "device", + "direction": "out", + "request": 0x31, + "value": 120, + "index": 0, + "data": [4, 8, 15, 16, 23, 42] + }; +chrome.experimental.usb.controlTransfer(deviceObj, transferInfo, optionalCallback); +</pre> + +<h3>Sending data - isochronous transfers</h3> + +<p> +Isochronous transfers are commonly used for streams of data. +Video and sound, for example, are good candidates for this transfer type. +To send an isochronous transfer, use: +</p> + +<pre> +chrome.experimental.usb.isochronousTransfer(deviceObj, isochronousTransferInfo, transferCallback) +</pre> + +<br> + +<table border="0"> + <tr> + <th scope="col"> Parameter </th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>deviceObj</td> + <td>Object sent on <code>findDevice()</code> callback.</td> + </tr> + <tr> + <td>isochronousTransferInfo</td> + <td>Parameter object with the values in the table below.</td> + </tr> + <tr> + <td>transferCallback()</td> + <td>Invoked when the transfer has completed. + Notice that this callback doesn't represent any response from the device. + It's just to notify your code that the asynchronous transfer request + has been processed and you can go ahead. + The device's response, if any, will always be sent through + the <code>onEvent()</code> callback set on <code>findDevice()</code>. + </td> + </tr> +</table> + +<p> +Values for <code>isochronousTransferInfo</code> object: +</p> + +<table border="0"> + <tr> + <th scope="col"> Value </th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>transferInfo (object)</td> + <td>A parameter object with the following parameters:<br> + <b>direction (string): </b>"in" or "out".<br> + <b>endpoint (integer): </b>defined by your device's protocol.<br> + <b>length (integer): </b>only used when direction is "in". + Notifies the device that this is the amount + of data the host is expecting in response<br> + <b>data (integer array): </b>defined by your device's protocol; + only used when direction is "out". + </td> + </tr> + <tr> + <td>packets (integer)</td> + <td>Total number of packets expected in this transfer.</td> + </tr> + <tr> + <td>packetLength (integer)</td> + <td>Expected length of each packet in this transfer.</td> + </tr> +</table> + +<p> +Example: +</p> + +<pre> +var transferInfo = { + "direction": "in", + "endpoint": 1, + "length": 2560 + }; +var isoTransferInfo = { + "transferInfo": transferInfo, + "packets": 20, + "packetLength": 128 +}; +chrome.experimental.usb.isochronousTransfer(deviceObj, isoTransferInfo, optionalCallback); +</pre> + +<h3>Sending data - bulk transfers</h3> + +<p> +Bulk transfer is a USB transfer type commonly used +to transfer a large amount of data reliably. +The method has three parameters: +</p> + +<pre> +chrome.experimental.usb.bulkTransfer(deviceObj, transferInfo, transferCallback) +</pre> + +<br> + +<table border="0"> + <tr> + <th scope="col"> Parameter </th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>deviceObj</td> + <td>Object sent on <code>findDevice()</code> callback.</td> + </tr> + <tr> + <td>transferInfo</td> + <td>Parameter object with the values in the table below.</td> + </tr> + <tr> + <td>transferCallback()</td> + <td>Invoked when the transfer has completed. + Notice that this callback doesn't represent any response from the device. + It's just to notify your code that the asynchronous transfer request + has been processed and you can go ahead. + The device's response, if any, will always be sent through + the <code>onEvent()</code> callback set on <code>findDevice()</code>. + </td> + </tr> +</table> + +<p> +Values for <code>transferInfo</code> object: +</p> + +<table border="0"> + <tr> + <th scope="col"> Value </th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>direction (string)</td> + <td>"in" or "out".</td> + </tr> + <tr> + <td>endpoint (integer)</td> + <td>Defined by your device's protocol.</td> + </tr> + <tr> + <td>length (integer)</td> + <td>Only used when direction is "in". + Notifies the device that this is the amount + of data the host is expecting in response.</td> + </tr> + <tr> + <td>data (integer array)</td> + <td>Defined by your device's protocol; + only used when direction is "out".</td> + </tr> +</table> + +<p> +Example: +</p> + +<pre> +var transferInfo = { + "direction": "out", + "endpoint": 1, + "data": [4, 8, 15, 16, 23, 42] + }; +</pre> + +<h3>Sending data - interrupt transfers</h3> + +<p> +Interrupt transfers are used to send important notifications. +Since all USB communication is initiated by the host, +host code usually polls the device periodically, +sending interrupt IN transfers that will make the device send data back +if there is anything on the interrupt queue. +The method has three parameters: +</p> + +<pre> +chrome.experimental.usb.interruptTransfer(deviceObj, transferInfo, transferCallback) +</pre> + +<br> + +<table border="0"> + <tr> + <th scope="col"> Parameter </th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>deviceObj</td> + <td>Object sent on <code>findDevice()</code> callback.</td> + </tr> + <tr> + <td>transferInfo</td> + <td>Parameter object with the values in the table below.</td> + </tr> + <tr> + <td>transferCallback()</td> + <td>Invoked when the transfer has completed. + Notice that this callback doesn't represent any response from the device. + It's just to notify your code that the asynchronous transfer request + has been processed and you can go ahead. + The device's response, if any, will always be sent through + the <code>onEvent()</code> callback set on <code>findDevice()</code>. + </td> + </tr> +</table> + +<p> +Values for <code>transferInfo</code> object: +</p> + +<table border="0"> + <tr> + <th scope="col"> Value </th> + <th scope="col"> Description </th> + </tr> + <tr> + <td>direction (string)</td> + <td>"in" or "out".</td> + </tr> + <tr> + <td>endpoint (integer)</td> + <td>Defined by your device's protocol.</td> + </tr> + <tr> + <td>length (integer)</td> + <td>Only used when direction is "in". + Notifies the device that this is the amount + of data the host is expecting in response.</td> + </tr> + <tr> + <td>data (integer array)</td> + <td>Defined by your device's protocol; + only used when direction is "out".</td> + </tr> + +<p> +Example: +</p> + +<pre> +var transferInfo = { + "direction": "in", + "endpoint": 1, + "length": 2 + }; +chrome.experimental.usb.interruptTransfer(deviceObj, transferInfo, optionalCallback); +</pre> + +<h3>Caveats</h3> + +<p> +On Linux, +you must have specific permission to access USB devices. +Create a file: <code>/etc/udev/rules.d/50-yourdevicename.rules</code>. +Add the following content: +</p> + +<pre> +SUBSYSTEM=="usb", ATTR{idVendor}=="yourdevicevendor", MODE="0664", GROUP="plugdev" +</pre> + +<p> +On MacOSX, +devices which expose a HID profile cannot be managed +using this low level API due to system restrictions. +Currently there is no workaround. +</p> + +<h2 id="serial">Accessing serial devices</h2> + +<p> +You can use the serial API to read +and write from a serial device. +</p> + +<h3>Manifest requirement</h3> + +<p> +The "serial" permission is not yet required; +"experimental" is enough for now: +</p> + +<pre> +"permissions": ["experimental"] +</pre> + +<h3>Listing available serial ports</h3> + +<p> +To get a list of available serial ports, +use the <code>getPorts()</code> method: +</p> + +<pre> +var onGetPorts = function(ports) { + for (var i=0; i<ports.length; i++) { + console.log(ports[i]); + } +} +chrome.experimental.serial.getPorts(onGetPorts); +</pre> + +<h3>Opening a serial device</h3> + +<p> +Here's how to open a serial device: +</p> + +<pre> +var onOpen = function(connectionInfo) { + // The serial device has been opened. Save its id to use later. + var conId = connectionInfo.connectionId; + // Do whatever you need to do with the opened device. +} +// Open the serial device /dev/ttyS01 +chrome.experimental.serial.open("/dev/ttyS01", onOpen); +</pre> + +<h3>Closing a serial device</h3> + +<p> +Here's how to close a serial device: +</p> + +<pre> +var onClose = function(result) { + console.log(“Serial port closed”); +} +chrome.experimental.serial.close(conId, onClose); +</pre> + +<h3>Reading from a serial device</h3> + +<p> +The serial API reads from the serial port and +delivers the read bytes as an ArrayBuffer. +There is no guarantee that all the available bytes will be read in one chunk +(they are currently read one byte per time, but this might change in the future). +The following procedure can accumulate read bytes until a new line is read, +and then call a listener with the <code>ArrayBuffer</code> bytes converted to a String: +</p> + +<pre> +var dataRead=''; + +var onCharRead=function(readInfo) { + if (!connectionInfo) { + return; + } + if (readInfo && readInfo.bytesRead>0 && readInfo.data) { + var str=ab2str(readInfo.data); + if (str[str.length-1]==='\n') { + dataRead+=str.substring(0, str.length-1); + onLineRead(dataRead); + dataRead=""; + } else { + dataRead+=str; + } + } + chrome.experimental.serial.read(connectionInfo.connectionId, onCharRead); + } + +/* Convert an ArrayBuffer to a String, using UTF-8 as the encoding scheme. + This is consistent with how Arduino sends characters by default */ + var ab2str=function(buf) { + return String.fromCharCode.apply(null, new Uint8Array(buf)); + }; +</pre> + +<h3>Writing to a serial device</h3> + +<p> +The writing routine is simpler than the reading, +since the writing can occur all at once. +The only catch is that if your data protocol is String based, +you have to convert your output string to an <code>ArrayBuffer</code> +to compy with write's method signature. +See the code below: +</p> + +<pre> +var writeSerial=function(str) { + chrome.experimental.serial.write(connectionInfo.connectionId, str2ab(str), onWrite); +} +var str2ab=function(str) { + var buf=new ArrayBuffer(str.length); + var bufView=new Uint8Array(buf); + for (var i=0; i<str.length; i++) { + bufView[i]=str.charCodeAt(i); + } + return buf; +} +</pre> + +<h3>Flushing a serial device buffer</h3> + +<p> +You can flush your serial device buffer by issuing the flush command on the API: +</p> + +<pre> +var flushSerial=function(str) { + chrome.experimental.serial.flush(connectionInfo.connectionId, onFlush); +} +</pre> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_identity.html b/chrome/common/extensions/docs/templates/articles/app_identity.html new file mode 100644 index 0000000..93d877e --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_identity.html @@ -0,0 +1,249 @@ +<h1>Identify User</h1> + + +<p> +Web authentication protocols utilize HTTP features, +but packaged apps run inside the app container; +they don’t load over HTTP and can’t perform redirects or set cookies. +</p> + +<p> +Use the <a href="experimental.identity.html">Chrome Identity API</a> +to authenticate users: +the <code>getAuthToken</code> for users logged into their Google Account and +the <code>launchWebAuthFlow</code> for users logged into a non-Google account. +If your app uses its own server to authenticate users, you will need to use the latter. +</p> + +<p class="note"> +<b>API Samples: </b> +Want to play with the code? +Check out the +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/identity">identity</a> sample. +</p> + +<h2 id="how">How it works</h2> + +<p> +Apps that use Google accounts +need to specify the OAuth2 client ID +and scopes in their manifest. +When users install the apps, +the OAuth2 permissions are displayed along with the Chrome permissions. +Once a user accepts the permissions, +the apps can get the access token +using <code>getAuthToken</code>. +</p> + +<p> +Apps that want to perform authentication +with any provider must call <code>launchAuthFlow</code>. +This method uses a browser pop-up to show the provider pages +and captures redirects to the specific URL patterns. +The redirect URLs are passed to the app +and the app extracts the token from the URL. +</p> + +<h2 id="google">Google account authentication</h2> + +<p> +Here are the five steps you need to complete: +</p> + +<ol> + <li>Add permissions to your manifest and upload your app.</li> + <li>Copy key in the installed <code>manifest.json</code> to your source manifest.</li> + <li>Get your client ID.</li> + <li>Update your manifest to include the client ID and scopes.</li> + <li>Get the authentication token.</li> +</ol> + +<h3>Add permissions and upload app</h3> + +<p> +The identity API is still experimental. +You need to make sure the experimental +and identity permissions are in your manifest. +You can then upload your app to the apps and extensions management page +(see <a href="publish_app.html">Publish</a>). +</p> + +<pre> +"permissions": [ + "experimental", + "identity" + ] +</pre> + +<h3>Copy key to your manifest</h3> + +<p> +You need to copy the key in the installed +<code>manifest.json</code> to your source manifest. +This ensures that the key isn't overridden anytime your reload your app +or share the app with other users. +It's not the most graceful task, but here's how it goes: +</p> + +<ol> + <li>Go to your + <a href="http://www.chromium.org/user-experience/user-data-directory">user data directory</a>. + Example on MacOs: <code>~/Library/Application\ Support/Google/Chrome/Default/Extensions</code></li> + <li>List the installed apps and extensions and match your app ID on the apps and extensions management page + to the same ID here.</li> + <li>Go to the installed app directory (this will be a version within the app ID). + Open the installed <code>manifest.json</code> + (pico is a quick way to open the file).</li> + <li>Copy the "key" in the installed <code>manifest.json</code> and paste it into your app's source manifest file.</li> +</ol> + +<h3>Get your client ID</h3> + +<p> +Setting up the client ID is currently not available externally +via <a href="https://devconsole-canary.corp.google.com/apis/">Google APIs Console</a>. +So to setup the OAuth2 client ID, +email <a href="mailto:chrome-apps-auth-requests@google.com">chrome-apps-auth-request@google.com</a> +with your stable app ID and +we will reply appropriately with your OAuth2 client ID. +</p> + +<h3>Update your manifest</h3> + +<p> +You need to update your manifest to include +the client ID and scopes. +Here's the sample "oauth2" for the +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/gdocs">gdocs sample</a>: +</p> + +<pre> +"oauth2": { + "client_id": "665859454684.apps.googleusercontent.com", + "scopes": [ + "https://docs.google.com/feeds/", + "https://docs.googleusercontent.com/", + "https://spreadsheets.google.com/feeds/", + "https://www.googleapis.com/auth/drive.file" + ] + } +</pre> + +<h3>Get the token</h3> + +<p> +You are now ready to get the auth token: +</p> + +<pre> +chrome.experimental.identity.getAuthToken(function(token) { }) +</pre> + +<h2 id="non">Non-Google account authentication</h2> + +<p> +Here are the three steps you need to complete: +</p> + +<ol> + <li>Register with the provider.</li> + <li>Add permissions for provider resources that your app will access.</li> + <li>Get the authentication token.</li> +</ol> + +<h3>Register with the provider</h3> + +<p> +You need to register an OAuth2 client ID with the provider +and configure the client ID as a website. +For the redirect URI to be entered during registration, +use the URL of the form: +<code>https://<extension-id>.chromiumapp.org/<anything-here></code> +</p> + +<p> +For example, if you app ID is abcdefghijklmnopqrstuvwxyzabcdef and +you want provider_cb to be the path, +to distinguish it with redirect URIs from other providers, +you should use: +<code>https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb</code> +</p> + +<h3>Add permissions for provider</h3> + +<p> +To make cross-original XHRs to Google API endpoints, +you need to whitelist those patterns in the permissions: +</p> + +<pre> +"permissions": [ + ... + "https://docs.google.com/feeds/", + "https://docs.googleusercontent.com/", + “https://www.website-of-provider-with-user-photos.com/photos/” +] +</pre> + +<h3>Get the token</h3> + +<p> +To get the token: +</p> + +<pre> +chrome.experimental.identity.launchWebAuthFlow( + {‘url’: ‘<url-to-do-auth>’, ‘interactive’: true}, + function(redirect_url) { // Extract token from redirect_url }); +</pre> + +<p> +The <url-to-do-auth> is whatever the URL is to do auth to the provider from a website. +For example, let us say that you are performing OAuth2 flow with a provider +and have registered your app with client id 123456789012345 and +you want access to user’s photos on the provider’s website: +<code>https://www.website-of-provider-with-user-photos.com/dialog/oauth?client_id=123456789012345&<br>redirect_uri=https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb&response_type=token&scope=user_photos</code> +</p> + +<p> +The provider will perform authentication and if appropriate, +will show login and/or approval UI to the user. +It will then redirect to +<code>https://abcdefghijklmnopqrstuvwxyzabcdef.chromiumapp.org/provider_cb#authToken=<auth-token></code> +</p> + +<p> +Chrome will capture that and invoke the callback +of the app with the full redirect URL. +The app should extract the token out of the URL. +</p> + +<h3>Interactive versus silent mode</h3> + +<p> +When calling <code>launchWebAuthFlow</code>, +you can pass a flag (‘interactive’: true in the example above) +indicating whether you want the API to be called +in interactive mode or not (aka silent mode). +If you invoke the API in interactive mode, +the user is shown UI, if necessary, +to get the token (signin UI and/or approval UI; +or for that matter any provider specific UI). +</p> + +<p> +If you invoke the API in silent mode, +the API will only return a token if the provider is able +to provide a token without showing any UI. +This is useful in cases when an app is doing the flow at app startup, for example, +or in general in cases where there is no user gesture involved. +</p> + +<p> +The best practice we suggest is to use silent mode +when there is no user gesture involved and use interactive mode +if there is a user gesture (for example, the user clicked the Sign In button in your app). +Note that we do not enforce gesture requirement. +</p> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_intents.html b/chrome/common/extensions/docs/templates/articles/app_intents.html new file mode 100644 index 0000000..533fb15 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_intents.html @@ -0,0 +1,225 @@ +<h1>Connect Apps with Web Intents</h1> + + +<p> +<a href="http://webintents.org/">Web Intents</a> +allow your application to quickly communicate +with other applications on the user's system and inside their browser. +Your application can register to handle specific user actions +such as editing images via the <code>manifest.json</code>; +your application can also invoke actions to be handled by other applications. +</p> + +<p>Pacakged apps use Web Intents as their primary mechanism for inter-app +communication.</p> + +<p class="note"> +<b>API Samples: </b> +Want to play with the code? +Check out the +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/webintents">webintents</a> sample. +</p> + +<h2 id="register">Register your app to handle an action</h2> + +<p> +You must supply the intent in the manifest: +</p> + +<pre> +"intents":{ + "http://webintents.org/edit" : [{ + "title" : "Best Image editing app", + "type" : ["image/*"] + }] +} +</pre> + +<p> +Unlike extensions and hosted apps, packaged applications do not +need a "href" attribute in the manifest declaration, this is +because packaged apps have a single entry point for +launch - the <code>onLaunched</code> event. +</p> + +<h2 id="content">Handling content types</h2> + +<p> +Your application can be the user's preferred choice for handling a file type. +For example, your application could handle viewing images or viewing pdfs. +You must supply the intent in the manifest +and use the "http://webintents.org/view" action: +</p> +<p>To be able declare your application's ability to view RSS and ATOM +feeds, you would add the following to your manifest. +</p> +<pre> +"intents": { + "http://webintents.org/view" : [{ + "title" : "RSS Feed Reader", + "type" : ["application/atom+xml", "application/rss+xml"] + }] +} +</pre> + +<p> +Your application will receive intent payload through the <code>onLaunched</code> event. +</p> +<pre> +chrome.app.runtime.onLaunched(function(intent) { + // App Launched + if(intent.action == "http://webinents.org/view" && + intent.type == "application/atom+xml") { + + // obtain the ATOM feed data. + var data = intent.data; + } +}); +</pre> + + +<h2 id="launching">Launching an app with a file</h2> +<p> +If your app handles the <code>view</code> intent, +it is possible to launch it from the command line with a file as a parameter. +</p> +<pre> +chrome.exe --app-id [app_id] [path_to_file] +</pre> +<p> +This will implicity launch your application with an intent payload populated +with the action set to "http://webintents.org/view", the type set to the +mime-type of the file and the data as a <code>FileEntry</code> object. +</p> +<pre> +chrome.app.runtime.onLaunched(function(intent) { + // App Launched + var data = intent.data; +}); +</pre> + +<h2 id="launching">Manipulating the file</h2> +<p> + When your application is launched with a file as the parameter + on the command-line, + the <code>intent.data</code> property is a <code>FileEntry</code>. + This is really cool because now you have a direct reference back to the physical + file on the disk, + and you can write data back to it. +</p> + +<pre> +chrome.app.runtime.onLaunched(function(intent) { + // App Launched + var data = intent.data; + if(data instanceof FileEntry) { + data.createWriter(function(writer) { + writer.onwriteend = function(e) { + console.log('Write completed.'); + }; + + writer.onerror = function(e) { + console.log('Write failed: ' + e.toString()); + }; + + // Create a new Blob and write it to log.txt. + var bb = new BlobBuilder(); // Note: window.WebKitBlobBuilder in Chrome 12. + bb.append('Lorem Ipsum'); + writer.write(bb.getBlob('text/plain')); + }); + } +}); +</pre> + +<h2 id="return">Returning data to calling application</h2> +<p> +Lots of applications want to cooperate +with the app that invoked them. +It's easy to send data back to the calling client +using <code>intent.postResult</code>: +</p> + +<pre> +chrome.app.runtime.onLaunched(function(intent) { + // App Launched + console.log(intent.action); + console.log(intent.type); + var data = intent.data; + // Do something with the data; + + intent.postResult(newData); +}); +</pre> + +<h2 id="localize">Localizing your app title</h2> + +<p> +If your application or extension is localized +as per the guidelines in +<a href="i18n.html">Internationalization (i18n)</a>, +you can localize the title of your intent in the picker +using the exact same infrastructure: +</p> + +<pre> +"intents": { + "http://webintents.org/edit" : [{ + "title" : "__MSG_intent_title__", + "type" : ["image/*"], + "disposition" : "inline" + }] +} +</pre> + +<h2 id="invoke">Invoking an action</h2> +<p> +If your application needs to be able +to use the functionality of another application, +it can simply ask the browser for it. +To ask for an application that supports image editing, +it's as simple as: +</p> + +<pre> +var intent = new WebKitIntent("http://webintents.org/edit", "image/png", "dataUri://"); + +window.navigator.webkitStartActivity(intent, function(data) { +// The data from the remote application is returned here. +}); +</pre> + +<h2 id="errors">Handling Errors and Exceptions</h2> +<p> + If your service application needs to signal to the client application + that an unrecoverable error has occurred, + then your application will need + to call <code>postError</code> on the intent object. + This will signal to the client’s onError callback + that something has gone wrong. +</p> + +<h3>Client</h3> + +<pre> +var intent = new WebKitIntent("http://webintents.org/edit", "image/png", "dataUri://"); + +var onSuccess = function(data) {}; +var onError = function() {}; + +window.navigator.webkitStartActivity(intent, onSuccess, onError); +</pre> + +<h3>Service</h3> +<pre> +chrome.app.runtime.onLaunched(function(intent) { + // App Launched + console.log(intent.action); + console.log(intent.type); + var data = intent.data; + // Do something with the data; + + intent.postResult(newData); +}); +</pre> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_known_issues.html b/chrome/common/extensions/docs/templates/articles/app_known_issues.html new file mode 100644 index 0000000..6e5148d --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_known_issues.html @@ -0,0 +1,57 @@ +<h1>Known Issues</h1> + +<p>Chrome's support for packaged apps is under active development and rapidly +evolving, so there are still a few rough edges. Here's a list of known issues +in the current <a href="https://tools.google.com/dlpage/chromesxs/">Chrome +Canary</a>:</p> + +<p id="known-issues"></p> +<p id="known-issues-error" style="position: absolute; top: -1000px; color: #333; padding: 1em; background: #eee;"> + The list of known issues cannot be loaded at this time. You may be able to + see them on the <a href="http://code.google.com/p/chromium/issues/list?q=label:Hotlist-AppsKnownIssues">Chromium bug tracker</a>. +</p> + +<script> + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function() { + if (xhr.readyState != 4) return; + + if (xhr.status != 200) { + // We can't use display none/block, since in that case the error paragraph + // would be stripped by the template processor. + document.getElementById('known-issues-error').style.position = 'static'; + return; + } + document.getElementById('known-issues').innerHTML = xhr.responseText; + }; + xhr.open( + 'GET', 'http://developer.chrome.com/app_known_issues_snippet.html', true); + xhr.send(null); +</script> + +<p> +If one of the above describes an issue you've run into, and you wish to be +updated when it's resolved, click the star icon on the page header. Do not +respond to the bug to say "me too" or ask "when will this be fixed?"; such +updates can cause hundreds of emails to be sent. Add a comment only if you have +information (such as a better test case or a suggested fix) that is likely +to be helpful. +</p> + +<h2>Can't find it in the list?</h2> + +<p> + If none of the issues listed above describe what you're running into, you + may wish to <a href="http://code.google.com/p/chromium/issues/list?can=2&q=Feature%3DApps+Type%3DBug">search</a> + the bug tracker, in case it has been reported but not marked as being known + yet. +</p> + +<p> + If you still can't find something that matches the problem you're having, you + can <a href="https://code.google.com/p/chromium/issues/entry?template=Defect report from user&labels=Feature-Apps,Type-Bug,Area-Internals,Pri-2">report + the bug</a> on the Chromium bug tracker. Please include as many details as + possible in your bug report, including Chrome version number, operating + system, and any other relevant configuration details. Bug reports that attach + a small app that exhibits the problem are especially appreciated. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_lifecycle.html b/chrome/common/extensions/docs/templates/articles/app_lifecycle.html new file mode 100644 index 0000000..7927cf7 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_lifecycle.html @@ -0,0 +1,230 @@ +<meta name="doc-family" content="apps"> +<h1>Manage App Lifecycle</h1> + + +<p> +The app runtime and event page are responsible +for managing the app lifecycle. +The app runtime manages app installation, +controls the event page, +and can shutdown the app at anytime. +The event page listens out for events from the app runtime +and manages what gets launched and how. +</p> + +<h2 id="lifecycle">How the lifecycle works</h2> + +<p> +The app runtime loads the event page +from a user's desktop and +the <code>onLaunch()</code> event is fired. +This event tells the event page what windows +to launch and their dimensions. +The lifecycle diagram here isn't the nicest to look at, +but it's practical (and we will make it nicer soon). +</p> + +<img src="{{static}}/images/applifecycle.png" + width="444" + height="329" + alt="how app lifecycle works"> + +<p> +When the event page has no executing JavaScript, +no pending callbacks, and no open windows, +the runtime unloads the event page and closes the app. +Before unloading the event page, +the <code>onSuspend()</code> event is fired. +This gives the event page opportunity +to do simple clean-up tasks +before the app is closed. +</p> + +<h2 id="eventpage">Create event page and windows</h2> + +<p> +All apps must have an event page. +This page contains the top-level logic of the application +with none of its own UI and is responsible +for creating the windows for all other app pages. +</p> + +<h3>Create event page</h3> + +<p> +To create the event page, +include the "background" field in the app manifest +and include the <code>background.js</code> in the scripts array. +Any library scripts used by the event page need to be added +to the "background" field first: +</p> + +<pre> +"background": { + "scripts": [ + "foo.js", + "background.js" + ] +} +</pre> + +<p> +Your event page must include the <code>onLaunched()</code> function. +This function is called +when your application is launched in any way: +</p> + +<pre> +chrome.app.runtime.onLaunched.addListener(function() { + // Tell your app what to launch and how. +}); +</pre> + +<h3>Create windows</h3> + +<p> +An event page may create one or more windows at its discretion. +By default, these windows are created with a script connection +to the event page and are directly scriptable by the event page. +</p> + +<p> +Windows can either be shells or panels. +Shell windows have no browser chrome. +Panel windows are the same as shell windows, +except they have different size and position restrictions, +for example, a chat panel. +</p> + +<p>Here's a sample <code>background.js</code> + with a 'shell' window:</p> + +<pre> +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('main.html', { + width: 800, + height: 600, + minWidth: 800, + minHeight: 600, + left: 100, + top: 100, + type: 'shell' + }); +}); +</pre> + +<p>Here's a sample <code>background.js</code> + with a 'panel' window: +</p> + +<pre> +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('index.html', { + width: 400, + height: 200, + type: 'panel' + }); +}); +</pre> + +<h3>Including Launch Data</h3> + +<p> +Depending on how your app is launched, +you may need to include launch data +in your event page. +By default, there is no launch data +when the app is started by the app launcher. +For apps that provide intents, +you need to include the +<code>launchData.intent</code> parameter. +</p> + +<p> +Web intents can be launched by other apps invoking their intent, +or by the runtime when apps are launched to view or edit files, +for example from the operating system file explorer. +To find out how to launch an app with web intents, +see <a href="app_intents.html#launching">Launching an App with a File</a>. +</p> + +<h2 id="runtime">Listening for app runtime events</h2> + +<p> +The app runtime controls the app installs, updates, and uninstalls. +You don't need to do anything to set up the app runtime, +but your event page can listen out for the <code>onInstalled()</code> event +to store local settings and the +<code>onSuspend()</code> event to do simple clean-up tasks +before the event page is unloaded. +</p> + +<h3>Storing local settings</h3> + +<p> +<code>chrome.runtime.onInstalled()</code> +is called when your app has first been installed, +or when it has been updated. +Any time this function is called, +the <code>onInstalled</code> event is fired. +The event page can listen for this event and use the +<a href="storage.html">Storage API</a> +to store and update local settings +(see also <a href="app_storage.html#options">Storage options</a>). +</p> + +<pre> +chrome.runtime.onInstalled.addListener(function() { + chrome.storage.local.set(object items, function callback); +}); +</pre> + +<h3>Preventing data loss</h3> + +<p> +Users can uninstall your app at any time. +When uninstalled, +no executing code or private data is left behind. +This can lead to data loss +since the users may be uninstalling an app +that has locally edited, unsynchronized data. +You should stash data to prevent data loss. +</p> + +<p> +At a minimum, +you should store user settings +so that if users reinstall your app, +their information is still available for reuse. +Using the Storage API +(<a href="storage.html#property-sync">chrome.storage.sync</a>), +user data can be automatically synced +with Chrome sync. +</p> + +<h3>Clean-up before app closes</h3> + +<p> +The app runtime sends the <code>onSuspend()</code> +event to the event page before unloading it. +Your event page can listen out for this event and +do clean-up tasks before the app closes. +</p> + +<p> +Once this event is fired, +the app runtime starts the process of closing the app: +all events stop firing and +JavaScript execution is halted. +Any asynchronous operations started +while handling this event are not guaranteed to complete. +Keep the clean-up tasks synchronous and simple. +</p> + +<pre> +chrome.runtime.onSuspend.addListener(function() { + // Do some simple clean-up tasks. +}); +</pre> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_network.html b/chrome/common/extensions/docs/templates/articles/app_network.html new file mode 100644 index 0000000..707f62b --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_network.html @@ -0,0 +1,178 @@ +<h1>Network Communications</h1> + +<p> +Packaged apps can act as a network client +for TCP and UDP connections. +This doc shows you how to use TCP and UDP +to send and receive data over the network. +For more information, +see the +<a href="socket.html">Sockets API</a>. +</p> + +<p class="note"> +<b>API Samples: </b> +Want to play with the code? +Check out the +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/telnet">telnet</a> +and <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/udp">udp</a> samples. +</p> + +<h2 id="manifest">Manifest requirements</h2> + +<p> +For packaged apps that use TCP or UDP, +add the "socket" permission to the manifest +and specify the IP end point permission rules. +For example: +</p> + +<pre> +"permissions": [ + {"socket": [ + "rule1", + "rule2", + ... + ]} + ] +</pre> + +<p> +The syntax of socket permission rules follows these patterns: +</p> + +<pre> +<socket-permission-rule> + := <op> | <op> ':' <host> | <op> ':' ':' <port> | + <op> ':' <host> ':' <port> + <op> := 'tcp-connect' | 'tcp-listen' | 'udp-bind' | 'udp-send-to' + <host> := '*' | '*.' <anychar except '/' and '*'>+ + <port> := '*' | <port number between 1 and 65535>) +</pre> + +<p> +Examples of socket permission rules: +</p> + +<ul> + <li>"tcp-connect:*:23" – connecting on port 23 of any hosts</li> + <li>"tcp-connect:www.example.com:23" – connecting port 23 of <em>www.example.com</em></li> + <li>"tcp-connect" – connecting any ports of any hosts</li> + <li>"udp-send-to::99" – sending UDP packet to port 99 of any hosts</li> + <li>"udp-bind::8899" – binding local port 8899 to receive UDP package</li> + <li>"tcp-listen::8080" – TCP listening on local port 8080</li> +</ul> + +<h2 id="tcp">Using TCP</h2> + +<p> +Packaged apps can make connections to any service that supports TCP. +</p> + +<h3>Connecting to a socket</h3> + +<p> +Here's a sample showing how to connect to a socket: +</p> + +<pre> +chrome.socket.create('tcp', {}, function(createInfo) { + socket.connect(createInfo.socketId, IP, PORT, onConnectedCallback); +}); +</pre> + +<p> +Keep a handle to the socketId so that +you can later read and write to this socket. +</p> + +<pre> +chrome.socket.write(socketId, arrayBuffer, onWriteCompleteCallback); +</pre> + +<h3>Reading to & writing from a socket</h3> + +<p> +Reading and writing from a socket uses ArrayBuffer objects. +</p> + +<pre> +chrome.socket.read(socketId, null, function(readInfo) { + if (readInfo.resultCode > 0) { + // readInfo.data is an arrayBuffer. + } +}); +</pre> + +<h3>Disconnecting from a socket</h3> + +<p>Here's how to disconnect:</p> + +<pre>chrome.socket.disconnect(socketId);</pre> + +<h2 id="udp">Using UDP</h2> + +<p> +Packaged apps can make connections to any service that supports UDP. +</p> + +<h3>Sending data</h3> + +<p> +Here's a sample showing how to send data +over the network using UDP: +</p> + +<pre> +// Create the Socket +chrome.socket.create('udp', '127.0.0.1', 1337, {}, + function(socketInfo) { + // The socket is created, now we want to connect to the service + var socketId = socketInfo.socketId; + chrome.socket.connect(socketId, function(result) { + // We are now connected to the socket so send it some data + chrome.socket.write(socketId, arrayBuffer, + function(sendInfo) { + console.log("wrote " + sendInfo.bytesWritten); + } + ); + }); + } +); +</pre> + +<h3>Receiving data</h3> + +<p> +This example is very similar to the 'Sending data' example +with the addition of a special handler in the 'create' method. +The parameter is an object with one value 'onEvent' +that is a function reference to the method +that will be called when data is available on the port. +</p> + +<pre> +// Handle the data response +var handleDataEvent = function(d) { + var data = chrome.socket.read(d.socketId); + console.log(data); +}; + +// Create the Socket +chrome.socket.create('udp', '127.0.0.1', 1337, { onEvent: handleDataEvent }, + function(socketInfo) { + // The socket is created, now we want to connect to the service + var socketId = socketInfo.socketId; + chrome.socket.connect(socketId, function(result) { + // We are now connected to the socket so send it some data + chrome.socket.write(socketId, arrayBuffer, + function(sendInfo) { + console.log("wrote " + sendInfo.bytesWritten); + } + ); + }); + } +); +</pre> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/app_storage.html b/chrome/common/extensions/docs/templates/articles/app_storage.html new file mode 100644 index 0000000..77c65d7 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/app_storage.html @@ -0,0 +1,229 @@ +<h1>Manage Data</h1> + + +<p> +Almost every aspect of app development involves some element +of sending or receiving data. +Starting with the basics, +you should use an MVC framework to help you design and implement your app +so that data is completely separate from the app's view on that data +(see <a href="app_frameworks.html">MVC Architecture</a>). +</p> + +<p> +You also need to think about how data is handled when your app is offline +(see <a href="offline_apps.html">Offline First</a>). +This doc briefly introduces the storage options +for sending, receiving, and saving data locally; +the remainder of the doc shows you how +to use Chrome's File System API +(see also the <a href="fileSystem.html">fileSystem API</a>). +</p> + +<p class="note"> +<b>API Samples: </b> +Want to play with the code? +Check out the +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/filesystem-access">filesystem-access</a> +and <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/storage">storage</a> samples. +</p> + +<h2 id="options">Storage options</h2> + +<p> +Packaged apps use many different mechanisms +to send and receive data. +For external data (resources, web pages), +you need to be aware of the +<a href="app_csp.html">Content Security Policy (CSP)</a>. +Similar to Chrome Extensions, +you can use +<a href="app_external.html#external">cross-origin XMLHttpRequests</a> +to communicate with remote servers. +You can also isolate external pages, +so that the rest of your app is secure +(see <a href="app_external.html#objecttag">Embed external web pages</a>). +With Web Intents, +your app can share data with other apps +(see <a href="app_intents.html">Connect Apps with Web Intents</a>). +</p> + +<p> +When saving data locally, +you can use the <a href="storage.html">Chrome Storage API</a> +to save small amounts of string data and +IndexedDB to save structured data. +With IndexedDB, you can persist JavaScript objects +to an object store and use the store's indexes to query data +(to learn more, see HTML5 Rock's +<a href="http://www.html5rocks.com/tutorials/indexeddb/todo/">Simple Todo List Tutorial</a>). +For all other types of data, +like binary data, +use the Filesystem API. +</p> + +<p> +Chrome's Filesystem API extends the +<a href="http://www.html5rocks.com/tutorials/file/filesystem/">HTML5 FileSystem API</a>; +apps can create, read, navigate, +and write to a sandboxed section +of the user's local file system. +With Chrome's File System API, +packaged apps can read and write files +to user-selected locations. +For example, +a photo-sharing app can use the File System API +to read and write any photos that a user selects. +</p> + +<h2 id="manifest">Adding file system permission</h2> + +<p> +To use Chrome's File System API, +you need to add the "fileSystem" permission to the manifest, +so that you can obtain permission from the user +to store persistent data. + +<pre> +"permissions": [ + "...", + "fileSystem" +] +</pre> + +<h2 id="import">User-options for selecting files</h2> + +<p> +Users expect to select files +in the same way they always do. +At a minimum, +they expect a 'choose file' button +and standard file-chooser. +If your app makes heavy use of file-handing, +you should also implement drag-and-drop +(see below and also check out +<a href="http://www.html5rocks.com/tutorials/dnd/basics/">Native HTML5 Drag and Drop</a>). +</p> + +<p> +If your app connects with other apps using +<a href="app_intents.html">Web Intents</a> +you can set up data sharing with those apps. +Users can view and/or write +to their files using a connected app +without having to do all sorts of extra steps +to move files back and forth. +</p> + +<h2 id="path">Obtaining the path of a fileEntry</h2> + +<p> +To get the full path +of the file the user selected, +<code>fileEntry</code>, +call <code>getDisplayPath()</code>: +</p> + +<pre> +function displayPath(fileEntry) { + chrome.fileSystem.getDisplayPath(fileEntry, function(path) { + console.log(path) + }); +} +</pre> + +<h2 id="drag">Implementing drag-and-drop</h2> + +<p> +If you need to implement drag-and-drop selection, +the drag-and-drop file controller +(<code>dnd.js</code>) in +the <a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/filesystem-access">filesystem-access</a> +sample is a good starting point. +The controller creates a file entry +from a <code>DataTransferItem</code> +via drag-and-drop. +In this example, +the <code>fileEntry</code> is set +to the first dropped item. +</p> + +<pre> +var dnd = new DnDFileController('body', function(data) { + var fileEntry = data.items[0].webkitGetAsEntry(); + displayPath(fileEntry); +}); +</pre> + +<h2 id="read">Reading a file</h2> + +<p> +The following code opens the file (read-only) and +reads it as text using a <code>FileReader</code> object. +If the file doesn't exist, an error is thrown. +</p> + +<pre> +var chosenFileEntry = null; + +chooseFileButton.addEventListener('click', function(e) { + chrome.fileSystem.chooseEntry({type: 'openFile'}, function(readOnlyEntry) { + + readOnlyEntry.file(function(file) { + var reader = new FileReader(); + + reader.onerror = errorHandler; + reader.onloadend = function(e) { + console.log(e.target.result); + }; + + reader.readAsText(file); + }); + }); +}); +</pre> + +<h2 id="write">Writing a file</h2> + +<p> +The two common use-cases +for writing a file are "Save" and "Save as". +The following code creates a +<code>writableEntry</code> +from the read-only <code>chosenFileEntry</code> and +writes the selected file to it. +</p> + +<pre> + chrome.fileSystem.getWritableEntry(chosenFileEntry, function(writableFileEntry) { + writableFileEntry.createWriter(function(writer) { + writer.onerror = errorHandler; + writer.onwriteend = callback; + + chosenFileEntry.file(function(file) { + writer.write(file); + }); + }, errorHandler); +}); +</pre> + +<p> +The following code creates a new file +with "Save as" functionality and +writes the new blob to the file +using the <code>writer.write()</code> method. +</p> + +<pre> +chrome.fileSystem.chooseEntry({type: 'saveFile'}, function(writableFileEntry) { + writableFileEntry.createWriter(function(writer) { + writer.onerror = errorHandler; + writer.onwriteend = function(e) { + console.log('write complete'); + }; + writer.write(new Blob(['1234567890'], {type: 'text/plain'})); + }, errorHandler); +}); +</pre> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/apps.html b/chrome/common/extensions/docs/templates/articles/apps.html new file mode 100644 index 0000000..d87b9eb0 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/apps.html @@ -0,0 +1,177 @@ +<h1>Packaged Apps</h1> + + +<p class="warning"> +<b>Warning: </b> +All content in this doc refers to the legacy version of packaged apps. +Your legacy packaged apps will still work, +but you won't have access to any of the new APIs. +Check out the new version of +<a href="/{{branchInfo.current}}/apps/about_apps.html">packaged apps</a>; +otherwise, you're missing out! +</p> + +<p> +This page talks about packaged apps—how +you implement them, +and how they're different from +extensions and ordinary web apps. +</p> + +<h2 id="overview">Overview</h2> + +<p> +A packaged app is a web app +that's bundled into a <code>.crx</code> file +and can use Chrome extension features. +You build a packaged app just like you build an extension, +except that a packaged app can't include a +<a href="browserAction.html">browser action</a> or +<a href="pageAction.html">page action</a>. +Instead, a packaged app includes at least one HTML file +within its <code>.crx</code> file +that provides the app's user interface. +</p> + +<p> +Packaged apps are a type of +<a href="http://code.google.com/chrome/apps/">installable web app</a>—a +web app that can be installed in Chrome. +The other type of installable web app is a +<a href="http://code.google.com/chrome/apps/docs/developers_guide.html">hosted app</a>, +which is an ordinary web app with a bit of additional metadata. +</p> + +<p> +If you're developing a web app for the Chrome Web Store, +you might want to use a packaged app +instead of a hosted app if any of the following are true: +</p> + +<ul> + <li> + You don't want to run a service to host your app. + </li> + <li> + You want to build an app that works really well offline. + </li> + <li> + You want tighter integration with Chrome, + using the extension APIs. + </li> +</ul> + +<p> +To learn more about +the differences between web apps and websites, +extensions and packaged apps, and packaged apps and hosted apps, +read these: +</p> + +<ul> + <li> <a href="http://code.google.com/chrome/webstore/docs/choosing.html">Choosing an App Type</a> </li> + <li> <a href="http://code.google.com/chrome/apps/articles/thinking_in_web_apps.html">Thinking in Web Apps</a> </li> + <li> <a href="http://code.google.com/chrome/webstore/articles/apps_vs_extensions.html">Extensions, Packaged Apps, and Hosted Apps in the Chrome Web Store</a> </li> +</ul> + + +<h2 id="manifest"> The manifest </h2> + +<p> +A packaged app's manifest can have any field +that's available to extensions, +except for "browser_action" and "page_action". +In addition, a packaged app's manifest <b>must</b> +have an "app" field. +Here is a typical manifest for a packaged app: +</p> + +<pre> +{ + "name": "My Awesome Racing Game", + "description": "Enter a world where a Vanagon can beat a Maserati", + "version": "1", + <b>"app": { + "launch": { + "local_path": "main.html" + } + },</b> + "icons": { + "16": "icon_16.png", + "128": "icon_128.png" + } +} +</pre> + +<p> +The "app" field has one subfield, "launch", +which specifies the <em>launch page</em> for the app—the +page (HTML file bundled into the <code>.crx</code> file) +that the browser goes to when the user clicks the app's icon +in the New Tab page. +The "launch" field can contain the following: +</p> + +<dl> + <dt>local_path:</dt> + <dd><em>Required.</em> + Specifies the launch page + as a relative path referring to a file + in the <code>.crx</code> package. + </dd> + <dt>container:</dt> + <dd> The value "panel" makes the app appear + in an app panel. + By default, or when you specify "tab", + the app appears in a tab. + + <!-- PENDING: In the overview + (or somewhere else before here) + we should show and define both app panels and tabs. + We should link to that place from here. --> + </dd> + <dt>height:</dt> + <dd> + If the container is set to "panel", + this integer specifies the height + of the panel in pixels. + For example, you might specify + <code>"height":400</code>. + Note that you don't use quotation marks in the value. + This field specifies the height of the area + to display contents in; + window decorations add a few more pixels to the total height. + If the container isn't a panel, this field is ignored. + </dd> + <dt>width:</dt> + <dd> + Similar to "height", + but specifies the width of the panel. + </dd> + </dd> +</dl> + +<p> +Packaged apps usually provide a 16x16 icon +to be used as the favicon for +tabs that contain app's pages. +They also should provide a 128x128 icon, +but not a 48x48 icon. +See the manifest documentation for the +<a href="manifest.html#icons">"icons" field</a> +for more information. +</p> + +<p> +For further details on what a packaged app's manifest can contain, see the +<a href="manifest.html">manifest documentation</a>. +</p> + +<h2 id="next">What next?</h2> + +<p> +Read the <a href="overview.html">Overview</a> to learn +basic concepts about extensions. +</p> + +<p class="backtotop"><a href="#top">Back to top</a></p> diff --git a/chrome/common/extensions/docs/templates/articles/autoupdate.html b/chrome/common/extensions/docs/templates/articles/autoupdate.html new file mode 100644 index 0000000..4c340bb --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/autoupdate.html @@ -0,0 +1,150 @@ +<h1>Autoupdating</h1> + + +<p>We want extensions to be autoupdated for some of the same reasons as Google Chrome itself: to incorporate bug and security fixes, add new features or performance enhancements, and improve user interfaces.</p> + +<p>If you publish your extension using the <a href="https://chrome.google.com/webstore/developer/dashboard">Chrome Developer Dashboard</a>, you can <em>ignore this page</em>. You can use the dashboard to release updated versions of your extension to users, as well as to the Chrome Web Store.</p> + +<p>If you want to host your extension somewhere other than the store, keep reading. +You should also read <a href="hosting.html">Hosting</a> and +<a href="packaging.html">Packaging</a>.</p> + + +<h2>Overview</h2> +<ul><li>An extension manifest may contain an "update_url" field, pointing to a location for doing update checks.</li> +<li>The content returned by an update check is an <em>update manifest</em> XML document listing the latest version of an extension.</li></ul> + +<p>Every few hours, the browser checks whether any installed extensions have an update URL. For each one, it makes a request to that URL looking for an update manifest XML file. If the update manifest mentions a version of an extension that is more recent than what's installed, the browser downloads and installs the new version. As with manual updates, the new <code>.crx</code> file must be signed with the same private key as the currently installed version.</p> + + +<h2>Update URL</h2> +<p>If you're hosting your own extension, you need to add the "update_url" field to your <a href="manifest.html"><code>manifest.json</code></a> file, +like this:</p> + +<pre>{ + "name": "My extension", + ... + <b>"update_url": "http://myhost.com/mytestextension/updates.xml"</b>, + ... +} +</pre> + +<h2>Update manifest</h2> +<p>The update manifest returned by the server should be an XML document that looks like this (highlights indicate parts you should modify):</p> + +<pre> +<?xml version='1.0' encoding='UTF-8'?> +<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'> + <app appid='<b>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</b>'> + <updatecheck codebase='<b>http://myhost.com/mytestextension/mte_v2.crx</b>' version='<b>2.0</b>' /> + </app> +</gupdate> +</pre> + +<p>This XML format is borrowed from that used by Omaha, Google's update infrastructure. See <a href="http://code.google.com/p/omaha/">http://code.google.com/p/omaha/</a> for more details. +The extensions system uses the following attributes +for the <strong><app></strong> +and <strong><updatecheck></strong> elements of the update manifest: +</p> + +<p><b>appid</b><br> +The extension ID, generated based on a hash of the extension's public key, +as described in <a href="packaging.html">Packaging</a>. You can find the +ID of an extension or packaged app by going to the Extensions page (<b>chrome://extensions</b>). + +Hosted apps, however, are not listed on the Extensions page. You can find the ID of any +app using the following steps: +</p> + +<ul> + <li> Open the app. You can do this by clicking its icon on the New Tab page.</li> + <li> Open the JavaScript console. You can do this by clicking the wrench icon + and choosing <b>Tools > JavaScript Console</b>.</li> + <li> Enter the following expression into the JavaScript console: <code>chrome.app.getDetails().id</code> + <p>The console shows the app's ID as a quoted string.</p> + </li> +</ul> + +<p><b>codebase</b><br> +A URL to the extension's <code>.crx</code> file.</p> + +<p><b>version</b><br> +Used by the client to determine whether it should download the <code>.crx</code> file specified by <code>codebase</code>. It should match the value of "version" in the <code>.crx</code> file's <code>manifest.json</code> file.</p> +<p>The update manifest XML file may contain information about multiple extensions by including multiple <app> elements.</p> + + +<h2>Testing</h2> +<p>The default update check frequency is several hours, +but you can force an update using the Extensions page's +<b>Update extensions now</b> button. +</p> + +<p> +Another option is to use the --extensions-update-frequency command-line flag to set a more frequent interval in seconds. For example, to make checks run every 45 seconds, run Google Chrome like this:</p> +<pre> +chrome.exe <b>--extensions-update-frequency=45</b></pre> + +<p>Note that this affects checks for all installed extensions, so consider the bandwidth and server load implications of this. You may want to temporarily uninstall all but the one extension you are testing with, and should not run with this option turned on during normal browser usage.</p> + + +<h2>Advanced usage: request parameters</h2> +<p>The basic autoupdate mechanism is designed to make the server-side work as easy as just dropping a static XML file onto any plain web server such as Apache, and updating that XML file as you release new versions of your extensions.</p> +<p>More advanced developers may wish to take advantage of the fact that we add on parameters to the request for the update manifest to indicate the extension ID and version. Then they can use the same update URL for all of their extensions, pointing to a URL running dynamic server-side code instead of a static XML file.</p> +<p>The format of the request parameters is:</p> +<p><code> ?x=<em><extension_data></em></code></p> +<p>Where <code><em><extension_data></em></code> is a URL-encoded string of the format:</p> +<p><code> <em>id=<id></em>&v=<em><version></em></code></p> + +<p>For example, say you have two extensions, +both of which point to the same update URL +(<code>http://test.com/extension_updates.php</code>): +</p> + +<ul> +<li> Extension 1 + <ul> + <li> ID: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" </li> + <li> Version: "1.1"</li> + </ul> +<li> Extension 2 + <ul> + <li> ID: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" </li> + <li> Version: "0.4"</li> + </ul> +</ul> + + +<p>The request to update each individual extension would be:</p> + +<ul> + <li> <code>http://test.com/extension_updates.php?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%26v%3D1.1</code> </li> + <li> <code>http://test.com/extension_updates.php?x=id%3Dbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb%26v%3D0.4</code> </li> +</ul> + +<p> +Multiple extensions can be listed in a single request for each unique update URL. +For the above example, if a user has both of the extensions installed, +then the two requests are merged into a single request:</p> +<p><code>http://test.com/extension_updates.php?x=id%3Daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa%26v%3D1.1&x=id%3Dbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb%26v%3D0.4</code></p> + +<p>If the number of installed extensions using the same update URL is large enough that a GET request URL is too long (over 2000 characters or so), the update check issues additional GET requests as necessary.</p> + +<p class="note"> +<b>Note:</b> +In the future, instead of issuing multiple GET requests, +a single POST request might be issued +with the request parameters in the POST body. +</p> + +<h2>Advanced usage: minimum browser version</h2> +<p>As we add more APIs to the extensions system, it's possible you will want to release an updated version of an extension that will work only with newer versions of the browser. While Google Chrome itself is autoupdated, it can take a few days before the majority of the user base has updated to any given new release. To ensure that a given extension update will apply only to Google Chrome versions at or higher than a specific version, you add the "prodversionmin" attribute to the <app> element in your update manifest. For example:</p> + +<pre><?xml version='1.0' encoding='UTF-8'?> +<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'> + <app appid='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'> + <updatecheck codebase='http://myhost.com/mytestextension/mte_v2.crx' version='2.0' <b>prodversionmin='3.0.193.0'</b>/> + </app> +</gupdate> +</pre> + +<p>This would ensure that users of this extension would autoupdate to version 2 only if they are running Google Chrome 3.0.193.0 or greater.</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/background_pages.html b/chrome/common/extensions/docs/templates/articles/background_pages.html new file mode 100644 index 0000000..7a7d6c8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/background_pages.html @@ -0,0 +1,160 @@ +<h1>Background Pages</h1> + + +<p id="eventPageWarning" class="warning"> + <em>Caution:</em> Consider using event pages instead. + <a href="event_pages.html">Learn more</a>. +</p> + +<p> +A common need for extensions is to have +a single long-running script to manage some task or state. +Background pages to the rescue. +</p> + +<p> +As the <a href="overview.html#arch">architecture overview</a> explains, +the background page is an HTML page that runs in the extension process. +It exists for the lifetime of your extension, +and only one instance of it at a time is active. +</p> + +<p> +In a typical extension with a background page, +the UI — +for example, the browser action or page action +and any options page — +is implemented by dumb views. +When the view needs some state, +it requests the state from the background page. +When the background page notices a state change, +the background page tells the views to update. +</p> + +<h2 id="manifest">Manifest</h2> + +<p> +Register your background page in the +<a href="manifest.html">extension manifest</a>. +In the common case, a background page +does not require any HTML markup. +These kind of background pages can be +implemented using JavaScript files alone, +like this: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"background": { + "scripts": ["background.js"] + }</b>, + ... +}</pre> + +<p> +A background page will be generated +by the extension system +that includes each of the files listed +in the <code>scripts</code> property. +</p> + +<p> +If you need to specify HTML +in your background page, you can +do that using the <code>page</code> +property instead: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"background": { + "page": "background.html" + }</b>, + ... +}</pre> + +<p> +If you need the browser to start up early—so +you can display notifications, for example—then +you might also want to specify the +<a href="manifest.html#permissions">"background" permission</a>. +</p> + + +<h2>Details</h2> + +<p> +You can communicate between your various pages using direct script calls, +similar to how frames can communicate. +The <a href="extension.html#method-getViews"><code>chrome.extension.getViews()</code></a> method +returns a list of window objects +for every active page belonging to your extension, +and the +<a href="extension.html#method-getBackgroundPage"><code>chrome.extension.getBackgroundPage()</code></a> method +returns the background page. +</p> + +<h2 id="example">Example</h2> + +<p> +The following code snippet demonstrates +how the background page +can interact with other pages in the extension. +It also shows how you can use +the background page to handle events +such as user clicks. +</p> + +<p> +The extension in this example +has a background page +and multiple pages created +(with +<a href="tabs.html#method-create"><code>chrome.tabs.create()</code></a>) +from a file named <code>image.html</code>. + +</p> + +<pre> +<em>//In background.js:</em> +// React when a browser action's icon is clicked. +chrome.browserAction.onClicked.addListener(function(tab) { + var viewTabUrl = chrome.extension.getURL('image.html'); + var imageUrl = <em>/* an image's URL */</em>; + + // Look through all the pages in this extension to find one we can use. + var views = chrome.extension.getViews(); + for (var i = 0; i < views.length; i++) { + var view = views[i]; + + // If this view has the right URL and hasn't been used yet... + if (view.location.href == viewTabUrl && !view.imageAlreadySet) { + + // ...call one of its functions and set a property. + view.setImageUrl(imageUrl); + view.imageAlreadySet = true; + break; // we're done + } + } +}); + +<em>//In image.html:</em> +<html> + <script> + function setImageUrl(url) { + document.getElementById('target').src = url; + } + </script> + + <body> + <p> + Image here: + </p> + + <img id="target" src="white.png" width="640" height="480"> + + </body> +</html> +</pre>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/contentSecurityPolicy.html b/chrome/common/extensions/docs/templates/articles/contentSecurityPolicy.html new file mode 100644 index 0000000..f6f7f29 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/contentSecurityPolicy.html @@ -0,0 +1,340 @@ +<h1>Content Security Policy (CSP)</h1> + + +<p> + In order to mitigate a large class of potental cross-site scripting issues, + Chrome's extension system has incorporated the general concept of + <a href="http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html"> + <strong>Content Security Policy (CSP)</strong> + </a>. This introduces some fairly strict policies that will make extensions + more secure by default, and provides you with the ability to create and + enforce rules governing the types of content that can be loaded and executed + by your extensions and applications. +</p> + +<p> + In general, CSP works as a black/whitelisting mechanism for resources loaded + or executed by your extensions. Defining a reasonable policy for your + extension enables you to carefully consider the resources that your extension + requires, and to ask the browser to ensure that those are the only resources + your extension has access to. These policies provide security over and above + the <a href="manifest.html#permissions">host permissions</a> your extension + requests; they're an additional layer of protection, not a replacement. +</p> + +<p> + On the web, such a policy is defined via an HTTP header or <code>meta</code> + element. Inside Chrome's extension system, neither is an appropriate + mechanism. Instead, an extension's policy is defined via the extension's + <a href="manifest.html"><code>manifest.json</code></a> file as follows: +</p> + +<pre>{ + ..., + "content_security_policy": "[POLICY STRING GOES HERE]" + ... +}</pre> + +<p class="note"> + For full details regarding CSP's syntax, please take a look at + <a href="http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#syntax"> + the Content Security Policy specification + </a>, and the <a href="http://www.html5rocks.com/en/tutorials/security/content-security-policy/"> + "An Introduction to Content Security Policy" + </a> article on HTML5Rocks. +</p> + +<h2 id="restrictions">Default Policy Restrictions</h2> + +<p> + Packages that do not define a <a href="manifestVersion.html"> + <code>manifest_version</code> + </a> have no default content security policy. Those that select + <code>manifest_version</code></a> 2, have a default content security policy + of: +</p> + +<pre>script-src 'self'; object-src 'self'</pre> + +<p> + This policy adds security by limiting extensions and applications in three + ways: +</p> + +<h3 id="JSEval">Eval and related functions are disabled</h3> + +<p>Code like the following does not work:</p> + +<pre> +alert(eval("foo.bar.baz")); +window.setTimeout("alert('hi')", 10); +window.setInteral("alert('hi')", 10); +new Function("return foo.bar.baz"); +</pre> + +<p>Evaluating strings of JavaScript like this is a common XSS attack vector. +Instead, you should write code like: + +<pre> +alert(foo && foo.bar && foo.bar.baz); +window.setTimeout(function() { alert('hi'); }, 10); +window.setInterval(function() { alert('hi'); }, 10); +function() { return foo && foo.bar && foo.bar.baz }; +</pre> + +<h3 id="JSExecution">Inline JavaScript will not be executed</h3> + +<p> + Inline JavaScript will not be executed. This restriction bans both inline + <code><script></code> blocks <strong>and</strong> inline event handlers + (e.g. <code><button onclick="..."></code>). +</p> + +<p> + The first restriction wipes out a huge class of cross-site scripting attacks + by making it impossible for you to accidentally execute script provided by a + malicious third-party. It does, however, require you to write your code with a + clean separation between content and behavior (which you should of course do + anyway, right?). An example might make this clearer. You might try to write a + <a href="browserAction.html#popups">Browser Action's popup</a> as a single + <code>popup.html</code> containing: +</p> + +<pre><!doctype html> +<html> + <head> + <title>My Awesome Popup!</title> + <script> + function awesome() { + // do something awesome! + } + + function totallyAwesome() { + // do something TOTALLY awesome! + } + + function clickHandler(element) { + setTimeout(<strong>"awesome(); totallyAwesome()"</strong>, 1000); + } + + function main() { + // Initialization work goes here. + } + </script> + </head> + <body onload="main();"> + <button <strong>onclick="clickHandler(this)"</strong>> + Click for awesomeness! + </button> + </body> +</html></pre> + +<p> + Three things will need to change in order to make this work the way you expect + it to: +</p> + +<ul> + <li> + The <code>clickHandler</code> definition needs to move into an external + JavaScript file (<code>popup.js</code> would be a good target). + </li> + <li> + <p>The inline event handler definitions must be rewritten in terms of + <code>addEventListener</code> and extracted into <code>popup.js</code>.</p> + <p>If you're currently kicking off your program's execution via code like + <code><body onload="main();"></code>, consider replacing it by hooking + into the document's <code>DOMContentLoaded</code> event, or the window's + <code>load</code> event, depending on your needs. Below we'll use the + former, as it generally triggers more quickly.</p> + </li> + <li> + The <code>setTimeout</code> call will need to be rewritten to avoid + converting the string <code>"awesome(); totallyAwesome()"</code> into + JavaScript for execution. + </li> +</ul> + +<p> + Those changes might look something like the following: +</p> + +<pre>popup.js: +========= + +function awesome() { + // Do something awesome! +} + +function totallyAwesome() { + // do something TOTALLY awesome! +} + +<strong>function awesomeTask() { + awesome(); + totallyAwesome(); +}</strong> + +function clickHandler(e) { + setTimeout(<strong>awesomeTask</strong>, 1000); +} + +function main() { + // Initialization work goes here. +} + +// Add event listeners once the DOM has fully loaded by listening for the +// `DOMContentLoaded` event on the document, and adding your listeners to +// specific elements when it triggers. +<strong>document.addEventListener('DOMContentLoaded', function () {</strong> + document.querySelector('button').addEventListener('click', clickHandler); + main(); +}); +</pre> +<pre>popup.html: +=========== + +<!doctype html> +<html> + <head> + <title>My Awesome Popup!</title> + <script <strong>src="popup.js"</strong>></script> + </head> + <body> + <button>Click for awesomeness!</button> + </body> +</html></pre> + +<p> + + +<h3 id="resourceLoading">Only local script and and object resources are loaded</h3> + +<p> + Script and object resources can only be loaded from the extension's + package, not from the web at large. This ensures that your extension only + executes the code you've specifically approved, preventing an active network + attacker from maliciously redirecting your request for a resource. +</p> + +<p> + Instead of writing code that depends on jQuery (or any other library) loading + from an external CDN, consider including the specific version of jQuery in + your extension package. That is, instead of: +</p> + +<pre><!doctype html> +<html> + <head> + <title>My Awesome Popup!</title> + <script src="<strong>http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js</strong>"></script> + </head> + <body> + <button>Click for awesomeness!</button> + </body> +</html></pre> + +<p> + Download the file, include it in your package, and write: +<p> + +<pre><!doctype html> +<html> + <head> + <title>My Awesome Popup!</title> + <script src="<strong>jquery.min.js</strong>"></script> + </head> + <body> + <button>Click for awesomeness!</button> + </body> +</html></pre> + +<h2 id="relaxing">Relaxing the default policy</h2> + +<h3 id="relaxing-inline-script">Inline Script</h3> + +<p> + There is no mechanism for relaxing the restriction against executing inline + JavaScript. In particular, setting a script policy that includes + <code>'unsafe-inline'</code> will have no effect. +</p> + +<h3 id="relaxing-remote-script">Remote Script</h3> + +<p> + If you have a need for some external JavaScript or object + resources, you can relax the policy to a limited extent by whitelisting + secure origins from which scripts should be accepted. We want to ensure that + executable resources loaded with an extension's elevated permissions are + exactly the resources you expect, and haven't been replaced by an active + network attacker. As <a + href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">man-in-the-middle + attacks</a> are both trivial and undetectable over HTTP, those origins will + not be accepted. Currently, we allow whitelisting origins with the following + schemes: <code>HTTPS</code>, <code>chrome-extension</code>, and + <code>chrome-extension-resource</code>. +</p> + +<p> + To ease development, we're also allowing the whitelisting of resources loaded + over HTTP from servers on your local machine. You may whitelist script and + object sources on any port of either <code>http://127.0.0.1</code> or + <code>http://localhost</code>. +</p> + +<p class="note"> + The restriction against resources loaded over HTTP applies only to those + resources which are directly executed. You're still free, for example, to + make XMLHTTPRequest connections to any origin you like; the default policy + doesn't restrict <code>connect-src</code> or any of the other CSP directives + in any way. +</p> + +<p> + A relaxed policy definition which allows script resources to be loaded from + <code>example.com</code> over HTTPS might look like: +</p> + +<pre>"content_security_policy": "script-src 'self' https://example.com; object-src 'self'"</pre> + +<p class="note"> + Note that both <code>script-src</code> and <code>object-src</code> are defined + by the policy. Chrome will not accept a policy that doesn't limit each of + these values to (at least) <code>'self'</code>. +</p> + +<p> + Making use of Google Analytics is the canonical example for this sort of + policy definition. It's common enough that we've provided an Analytics + boilerplate of sorts in the <a href="samples.html#analytics">Event Tracking + with Google Analytics</a> sample extension, and a +<a href="tut_analytics.html">brief tutorial</a> that goes into more detail. +</p> + +<h3 id="relaxing-eval">Evaluated JavaScript</h3> + +<p> + The policy against <code>eval()</code> and its relatives like + <code>setTimeout(String)</code>, <code>setInterval(String)</code>, and + <code>new Function(String)</code> can be relaxed by adding + <code>'unsafe-eval'</code> to your policy: +</p> + +<pre>"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"</pre> + +<p> + However, we strongly recommend against doing this. These functions are + notorious XSS attack vectors. +</p> + +<h2 id="tightening">Tightening the default policy</h2> + +<p> + You may, of course, tighten this policy to whatever extent your extension + allows in order to increase security at the expense of convenience. To specify + that your extension can only load resources of <em>any</em> type (images, etc) + from its own package, for example, a policy of <code>default-src 'self'</code> + would be appropriate. The <a href="samples.html#mappy">Mappy</a> sample + extension is a good example of an extension that's been locked down above and + beyond the defaults. +</p> diff --git a/chrome/common/extensions/docs/templates/articles/content_scripts.html b/chrome/common/extensions/docs/templates/articles/content_scripts.html new file mode 100644 index 0000000..23e46bf --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/content_scripts.html @@ -0,0 +1,461 @@ +<h1>Content Scripts</h1> + + +<p> +Content scripts are JavaScript files that run in the context of web pages. +By using the standard +<a href="http://www.w3.org/TR/DOM-Level-2-HTML/">Document +Object Model</a> (DOM), +they can read details of the web pages the browser visits, +or make changes to them. +</p> + +<p> +Here are some examples of what content scripts can do: +</p> + +<ul> + <li>Find unlinked URLs in web pages and convert them into hyperlinks + <li>Increase the font size to make text more legible + <li>Find and process <a href="http://microformats.org/">microformat</a> data in the DOM +</ul> + +<p> +However, content scripts have some limitations. +They <b>cannot</b>: +</p> + +<ul> + <li> + Use chrome.* APIs + (except for parts of + <a href="extension.html"><code>chrome.extension</code></a>) + </li> + <li> + Use variables or functions defined by their extension's pages + </li> + <li> + Use variables or functions defined by web pages or by other content scripts + </li> +</ul> + +<p> +These limitations aren't as bad as they sound. +Content scripts can <em>indirectly</em> use the chrome.* APIs, +get access to extension data, +and request extension actions +by exchanging <a href="messaging.html">messages</a> +with their parent extension. +Content scripts can also +make <a href="xhr.html">cross-site XMLHttpRequests</a> +to the same sites as their parent extensions, +and they can +<a href="#host-page-communication">communicate with web pages</a> +using the shared DOM. +For more insight into what content scripts can and can't do, +learn about the +<a href="#execution-environment">execution environment</a>. +</p> + +<h2 id="registration">Manifest</h2> + +<p>If your content script's code should always be injected, +register it in the +<a href="manifest.html">extension manifest</a> +using the <code>content_scripts</code> field, +as in the following example. +</p> + +<pre>{ + "name": "My extension", + ... + <b>"content_scripts": [ + { + "matches": ["http://www.google.com/*"], + "css": ["mystyles.css"], + "js": ["jquery.js", "myscript.js"] + } + ]</b>, + ... +}</pre> + +<p> +If you want to inject the code only sometimes, +use the +<a href="manifest.html#permissions"><code>permissions</code></a> field instead, +as described in <a href="#pi">Programmatic injection</a>. +</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "tabs", "http://www.google.com/*" + ]</b>, + ... +}</pre> + +<p> +Using the <code>content_scripts</code> field, +an extension can insert multiple content scripts into a page; +each of these content scripts can have multiple JavaScript and CSS files. +Each item in the <code>content_scripts</code> array +can have the following properties:</p> + +<table> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + </tr> + <tr> + <td><code>matches</code></td> + <td>array of strings</td> + <td><em>Required.</em> + Specifies which pages this content script will be injected into. + See <a href="match_patterns.html">Match Patterns</a> + for more details on the syntax of these strings + and <a href="#match-patterns-globs">Match patterns and globs</a> + for information on how to exclude URLs.</td> + </tr> + <tr> + <td><code>exclude_matches</code></td> + <td>array of strings</td> + <td><em>Optional.</em> + Excludes pages that this content script would otherwise be + injected into. + See <a href="match_patterns.html">Match Patterns</a> + for more details on the syntax of these strings + and <a href="#match-patterns-globs">Match patterns and globs</a> + for information on how to exclude URLs.</td> + </tr> + <tr> + <td><code>css<code></td> + <td>array of strings</td> + <td><em>Optional.</em> + The list of CSS files to be injected into matching pages. These are injected in the order they appear in this array, before any DOM is constructed or displayed for the page.</td> + </tr> + <tr> + <td><code>js<code></td> + <td><nobr>array of strings</nobr></td> + <td><em>Optional.</em> + The list of JavaScript files to be injected into matching pages. These are injected in the order they appear in this array.</td> + </tr> + <tr id="run_at"> + <td><code>run_at<code></td> + <td>string</td> + <td><em>Optional.</em> + Controls when the files in <code>js</code> are injected. Can be "document_start", "document_end", or "document_idle". Defaults to "document_idle". + + <br><br> + + In the case of "document_start", the files are injected after any files from <code>css</code>, but before any other DOM is constructed or any other script is run. + + <br><br> + + In the case of "document_end", the files are injected immediately after the DOM is complete, but before subresources like images and frames have loaded. + + <br><br> + + In the case of "document_idle", the browser chooses a time to inject scripts between "document_end" and immediately after the <code><a href="http://www.whatwg.org/specs/web-apps/current-work/#handler-onload">window.onload</a></code> event fires. The exact moment of injection depends on how complex the document is and how long it is taking to load, and is optimized for page load speed. + + <br><br> + + <b>Note:</b> With "document_idle", content scripts may not necessarily receive the <code>window.onload</code> event, because they may run after it has + already fired. In most cases, listening for the <code>onload</code> event is unnecessary for content scripts running at "document_idle" because they are guaranteed to run after the DOM is complete. If your script definitely needs to run after <code>window.onload</code>, you can check if <code>onload</code> has already fired by using the <code><a href="http://www.whatwg.org/specs/web-apps/current-work/#dom-document-readystate">document.readyState</a></code> property.</td> + </tr> + <tr> + <td><code>all_frames<code></td> + <td>boolean</td> + <td><em>Optional.</em> + Controls whether the content script runs in all frames of the matching page, or only the top frame. + <br><br> + Defaults to <code>false</code>, meaning that only the top frame is matched.</td> + </tr> + <tr> + <td><code>include_globs</code></td> + <td>array of string</td> + <td><em>Optional.</em> + Applied after <code>matches</code> to include only those URLs that also match this glob. Intended to emulate the <a href="http://wiki.greasespot.net/Metadata_Block#.40include"><code>@include</code></a> Greasemonkey keyword. + See <a href="#match-patterns-globs">Match patterns and globs</a> below for more details.</td> + </tr> + <tr> + <td><code>exclude_globs</code></td> + <td>array of string</td> + <td><em>Optional.</em> + Applied after <code>matches</code> to exclude URLs that match this glob. + Intended to emulate the <a href="http://wiki.greasespot.net/Metadata_Block#.40include"><code>@exclude</code></a> Greasemonkey keyword. + See <a href="#match-patterns-globs">Match patterns and globs</a> below for more details.</td> + </tr> +</table> + +<h3 id="match-patterns-globs">Match patterns and globs</h3> + +<p> +The content script will be injected into a page if its URL matches any <code>matches</code> pattern and any <code>include_globs</code> pattern, as long as the URL doesn't also match an <code>exclude_matches</code> or <code>exclude_globs</code> pattern. + +Because the <code>matches</code> property is required, <code>exclude_matches</code>, <code>include_globs</code>, and <code>exclude_globs</code> can only be used to limit which pages will be affected. +</p> + +<p> +For example, assume <code>matches</code> is <code>["http://*.nytimes.com/*"]</code>: +</p> +<ul> +<li>If <code>exclude_matches</code> is <code>["*://*/*business*"]</code>, then the content script would be injected into "http://www.nytimes.com/health" but not into "http://www.nytimes.com/business".</li> +<li>If <code>include_globs</code> is <code>["*nytimes.com/???s/*"]</code>, then the content script would be injected into "http:/www.nytimes.com/arts/index.html" and "http://www.nytimes.com/jobs/index.html" but not into "http://www.nytimes.com/sports/index.html".</li> +<li>If <code>exclude_globs</code> is <code>["*science*"]</code>, then the content script would be injected into "http://www.nytimes.com" but not into "http://science.nytimes.com" or "http://www.nytimes.com/science".</li> +</ul> +<p> + +<p> +Glob properties follow a different, more flexible syntax than <a href="match_patterns.html">match patterns</a>. Acceptable glob strings are URLs that may contain "wildcard" asterisks and question marks. The asterisk (*) matches any string of any length (including the empty string); the question mark (?) matches any single character. +</p> + +<p> +For example, the glob "http://???.example.com/foo/*" matches any of the following: +</p> +<ul> + <li>"http://www.example.com/foo/bar"</li> + <li>"http://the.example.com/foo/"</li> +</ul> +<p> +However, it does <em>not</em> match the following: +</p> +<ul> + <li>"http://my.example.com/foo/bar"</li> + <li>"http://example.com/foo/"</li> + <li>"http://www.example.com/foo"</li> +</ul> + +<h2 id="pi">Programmatic injection</h2> + +<p> +Inserting code into a page programmatically is useful +when your JavaScript or CSS code +shouldn't be injected into every single page +that matches the pattern — +for example, if you want a script to run +only when the user clicks a browser action's icon. +</p> + +<p> +To insert code into a page, +your extension must have +<a href="xhr.html#requesting-permission">cross-origin permissions</a> +for the page. +It also must be able to use the <code>chrome.tabs</code> module. +You can get both kinds of permission +using the manifest file's +<a href="manifest.html#permissions">permissions</a> field. +</p> + +<p> +Once you have permissions set up, +you can inject JavaScript into a page by calling +<a href="tabs.html#method-executeScript"><code>executeScript()</code></a>. +To inject CSS, use +<a href="tabs.html#method-insertCSS"><code>insertCSS()</code></a>. +</p> + +<p> +The following code +(from the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/make_page_red/">make_page_red</a> example) +reacts to a user click +by inserting JavaScript into the current tab's page +and executing the script. +</p> + +<pre> +<em>/* in background.html */</em> +chrome.browserAction.onClicked.addListener(function(tab) { + chrome.tabs.executeScript(null, + {code:"document.body.bgColor='red'"}); +}); + +<em>/* in manifest.json */</em> +"permissions": [ + "tabs", "http://*/*" +], +</pre> + +<p> +When the browser is displaying an HTTP page +and the user clicks this extension's browser action, +the extension sets the page's <code>bgcolor</code> property to 'red'. +The result, +unless the page has CSS that sets the background color, +is that the page turns red. +</p> + +<p> +Usually, instead of inserting code directly (as in the previous sample), +you put the code in a file. +You inject the file's contents like this: +</p> + +<pre>chrome.tabs.executeScript(null, {file: "content_script.js"});</pre> + + +<h2 id="execution-environment">Execution environment</h2> + +<p>Content scripts execute in a special environment called an <em>isolated world</em>. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page. It looks to each content script as if there is no other JavaScript executing on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any functions or access any variables defined by content scripts. + +<p>For example, consider this simple page: + +<pre>hello.html +========== +<html> + <button id="mybutton">click me</button> + <script> + var greeting = "hello, "; + var button = document.getElementById("mybutton"); + button.person_name = "Bob"; + button.addEventListener("click", function() { + alert(greeting + button.person_name + "."); + }, false); + </script> +</html></pre> + +<p>Now, suppose this content script was injected into hello.html: + +<pre>contentscript.js +================ +var greeting = "hola, "; +var button = document.getElementById("mybutton"); +button.person_name = "Roberto"; +button.addEventListener("click", function() { + alert(greeting + button.person_name + "."); +}, false); +</pre> + +<p>Now, if the button is pressed, you will see both greetings. + +<p>Isolated worlds allow each content script to make changes to its JavaScript environment without worrying about conflicting with the page or with other content scripts. For example, a content script could include JQuery v1 and the page could include JQuery v2, and they wouldn't conflict with each other. + +<p>Another important benefit of isolated worlds is that they completely separate the JavaScript on the page from the JavaScript in extensions. This allows us to offer extra functionality to content scripts that should not be accessible from web pages without worrying about web pages accessing it. + + +<h2 id="host-page-communication">Communication with the embedding page</h2> + +<p>Although the execution environments of content scripts and the pages that host them are isolated from each other, they share access to the page's DOM. If the page wishes to communicate with the content script (or with the extension via the content script), it must do so through the shared DOM.</p> +<p>An example can be accomplished using window.postMessage (or window.webkitPostMessage for Transferable objects):</p> +<pre>contentscript.js +================ +var port = chrome.extension.connect(); + +window.addEventListener("message", function(event) { + // We only accept messages from ourselves + if (event.source != window) + return; + + if (event.data.type && (event.data.type == "FROM_PAGE")) { + console.log("Content script received: " + event.data.text); + port.postMessage(event.data.text); + } +}, false);</pre> +<pre>http://foo.com/example.html +=========================== +document.getElementById("theButton").addEventListener("click", function() { + window.postMessage({ type: "FROM_PAGE", text: "Hello from the webpage!" }, "*"); +}, false);</pre> +<p>In the above example, example.html (which is not a part of the extension) posts messages to itself, which are intercepted and inspected by the content script, and then posted to the extension process. In this way, the page establishes a line of communication to the extension process. The reverse is possible through similar means.</p> + +<h2 id="security-considerations">Security considerations</h2> + +<p>When writing a content script, you should be aware of two security issues. +First, be careful not to introduce security vulnerabilities into the web site +your content script is injected into. For example, if your content script +receives content from another web site (for example, by making an <a +href="messaging.html">XMLHttpRequest</a>), +be careful to filter that content for <a +href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site +scripting</a> attacks before injecting the content into the current page. +For example, prefer to inject content via innerText rather than innerHTML. +Be especially careful when retrieving HTTP content on an HTTPS page because +the HTTP content might have been corrupted by a network <a +href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">"man-in-the-middle"</a> +if the user is on a hostile network.</p> + +<p>Second, although running your content script in an isolated world provides +some protection from the web page, a malicious web page might still be able +to attack your content script if you use content from the web page +indiscriminately. For example, the following patterns are dangerous: +<pre>contentscript.js +================ +var data = document.getElementById("json-data") +// WARNING! Might be evaluating an evil script! +var parsed = eval("(" + data + ")") + +contentscript.js +================ +var elmt_id = ... +// WARNING! elmt_id might be "); ... evil script ... //"! +window.setTimeout("animate(" + elmt_id + ")", 200); +</pre> +<p>Instead, prefer safer APIs that do not run scripts:</p> +<pre>contentscript.js +================ +var data = document.getElementById("json-data") +// JSON.parse does not evaluate the attacker's scripts. +var parsed = JSON.parse(data) + +contentscript.js +================ +var elmt_id = ... +// The closure form of setTimeout does not evaluate scripts. +window.setTimeout(function() { + animate(elmt_id); +}, 200); +</pre> + +<h2 id="extension-files">Referring to extension files</h2> + +<p> +Get the URL of an extension's file using +<code>chrome.extension.getURL()</code>. +You can use the result +just like you would any other URL, +as the following code shows. +</p> + + +<pre> +<em>//Code for displaying <extensionDir>/images/myimage.png:</em> +var imgURL = <b>chrome.extension.getURL("images/myimage.png")</b>; +document.getElementById("someImage").src = imgURL; +</pre> + +<h2 id="examples"> Examples </h2> + +<p> +You can find many +<a href="samples.html#script">examples that use content scripts</a>. +A simple example of communication via messages is in the +<a href="samples.html#51a83d2ba3a32e3ff1bdb624d4e18ccec4c4038e">timer sample</a>. +See <a href="samples.html#ede3c47b7757245be42ec33fd5ca63df4b490066">make_page_red</a> and +<a href="samples.html#028eb5364924344029bcbe1d527f132fc72b34e5">email_this_page</a> +for examples of programmatic injection. +</p> + + +<h2 id="videos"> Videos </h2> + +<p> +The following videos discuss concepts that are important for content scripts. +The first video describes content scripts and isolated worlds. +</p> + +<p> +<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/laLudeUmXHM?rel=0" frameborder="0" allowfullscreen></iframe> +</p> + +<p> +The next video describes message passing, +featuring an example of a content script +sending a request to its parent extension. +</p> + +<p> +<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/B4M_a7xejYI?rel=0" frameborder="0" allowfullscreen></iframe> +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/crx.html b/chrome/common/extensions/docs/templates/articles/crx.html new file mode 100644 index 0000000..b761b85 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/crx.html @@ -0,0 +1,147 @@ +<h1>CRX Package Format</h1> + + +<p> +CRX files are ZIP files with a special header and the <code>.crx</code> file +extension. +</p> + +<h2>Package header</h2> + +<p> +The header contains the author's public key and the extension's signature. +The signature is generated from the ZIP file using SHA-1 with the +author's private key. The header requires a little-endian byte ordering with +4-byte alignment. The following table describes the fields of +the <code>.crx</code> header in order: +</p> + +<table> + <tr> + <th>Field</th><th>Type</th><th>Length</th><th>Value</th><th>Description</th> + </tr> + <tr> + <td><em>magic number</em></td><td>char[]</td><td>32 bits</td><td>Cr24</td> + <td> + Chrome requires this constant at the beginning of every <code>.crx</code> + package. + </td> + </tr> + <tr> + <td><em>version</em></td><td>unsigned int</td><td>32 bits</td><td>2</td> + <td>The version of the <code>*.crx</code> file format used (currently 2).</td> + </tr> + <tr> + <td><em>public key length</em></td><td>unsigned int</td><td>32 bits</td> + <td><i>pubkey.length</i></td> + <td> + The length of the RSA public key in <em>bytes</em>. + </td> + </tr> + <tr> + <td><em>signature length</em></td><td>unsigned int</td><td>32 bits</td> + <td><i>sig.length</i></td> + <td> + The length of the signature in <em>bytes</em>. + </td> + </tr> + <tr> + <td><em>public key</em></td><td>byte[]</td><td><i>pubkey.length</i></i></td> + <td><i>pubkey.contents</i></td> + <td> + The contents of the author's RSA public key, formatted as an X509 + SubjectPublicKeyInfo block. + </td> + </tr> + <tr> + <td><em>signature</em></td><td>byte[]</td><td><i>sig.length</i></td> + <td><i>sig.contents</i></td> + <td> + The signature of the ZIP content using the author's private key. The + signature is created using the RSA algorithm with the SHA-1 hash function. + </td> + </tr> +</table> + +<h2>Extension contents</h2> + +<p> +The extension's ZIP file is appended to the <code>*.crx</code> package after the +header. This should be the same ZIP file that the signature in the header +was generated from. +</p> + +<h2>Example</h2> + +<p> +The following is an example hex dump from the beginning of a <code>.crx</code> +file. +</p> + +<pre> +43 72 32 34 # "Cr24" -- the magic number +02 00 00 00 # 2 -- the crx format version number +A2 00 00 00 # 162 -- length of public key in bytes +80 00 00 00 # 128 -- length of signature in bytes +........... # the contents of the public key +........... # the contents of the signature +........... # the contents of the zip file + +</pre> + +<h2 id="scripts">Packaging scripts</h2> +<p> +Members of the community have written the following scripts to package +<code>.crx</code> files. +</p> + +<h3 id="ruby">Ruby</h3> +<blockquote> +<a href="http://github.com/Constellation/crxmake">github: crxmake</a> +</blockquote> + +<h3>Bash</h3> +<pre> +#!/bin/bash -e +# +# Purpose: Pack a Chromium extension directory into crx format + +if test $# -ne 2; then + echo "Usage: crxmake.sh <extension dir> <pem path>" + exit 1 +fi + +dir=$1 +key=$2 +name=$(basename "$dir") +crx="$name.crx" +pub="$name.pub" +sig="$name.sig" +zip="$name.zip" +trap 'rm -f "$pub" "$sig" "$zip"' EXIT + +# zip up the crx dir +cwd=$(pwd -P) +(cd "$dir" && zip -qr -9 -X "$cwd/$zip" .) + +# signature +openssl sha1 -sha1 -binary -sign "$key" < "$zip" > "$sig" + +# public key +openssl rsa -pubout -outform DER < "$key" > "$pub" 2>/dev/null + +byte_swap () { + # Take "abcdefgh" and return it as "ghefcdab" + echo "${1:6:2}${1:4:2}${1:2:2}${1:0:2}" +} + +crmagic_hex="4372 3234" # Cr24 +version_hex="0200 0000" # 2 +pub_len_hex=$(byte_swap $(printf '%08x\n' $(ls -l "$pub" | awk '{print $5}'))) +sig_len_hex=$(byte_swap $(printf '%08x\n' $(ls -l "$sig" | awk '{print $5}'))) +( + echo "$crmagic_hex $version_hex $pub_len_hex $sig_len_hex" | xxd -r -p + cat "$pub" "$sig" "$zip" +) > "$crx" +echo "Wrote $crx" +</pre>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/develop_apps.html b/chrome/common/extensions/docs/templates/articles/develop_apps.html new file mode 100644 index 0000000..be50d0b3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/develop_apps.html @@ -0,0 +1,49 @@ +<h1>Before You Start</h1> + + +<p> +This documentation tells you how to write packaged apps. +All developers, however, should know that the new APIs +for packaged apps are being released as a developer preview. +This means that they are evolving daily, +and anything you read now might be different in the near future. +Please keep up to date with the API reference and documentation. +If you hit any stumbling blocks, +feedback is welcome at +<a href="http://groups.google.com/a/chromium.org/group/chromium-apps">#chromium-apps</a> +</p> + +<p class="caution"> +<b>Note:</b> +If you've written packaged apps before, +your <a href="http://code.google.com/chrome/extensions/apps.html">legacy packaged apps</a> +will still work the way they always have, +but they won't have access to the new APIs. +</p> + +<h2 id="start">Where to start</h2> + +<p> +The <a href="about_apps.html">Getting Started</a> guide is a great place to start. +It's fast reading; shouldn't take more than 10 minutes to read all three docs. +After the Getting Started guide, +decide what's most relevant to you. +The <a href="app_lifecycle.html">Fundamentals</a> guide covers +the details of the app and data lifecycle, +or learn more about good app design +by reading <a href="app_frameworks.html">MVC Architecture</a>. +We've also got lots of sample code in our repository +that is linked to directly from the documentation. +</p> + +<p> +If you're familiar with the Chrome extension docs, +then the Reference docs should seem familiar. +Packaged apps and extensions share a common platform. +They can access many of the same APIs, +they have the same manifest and permissions format. +Many of the reference docs are shared; +we've filtered accessibility to docs that aren't shared. +</p> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/devguide.html b/chrome/common/extensions/docs/templates/articles/devguide.html new file mode 100644 index 0000000..fda83db --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/devguide.html @@ -0,0 +1,145 @@ +<h1>Developer's Guide</h1> + +<p> +These pages assume you've completed +the <a href="getstarted.html">Getting Started</a> tutorial +and <a href="overview.html">Overview</a>. +Unless otherwise stated, everything in this page +applies to packaged apps, as well as extensions. +</p> + +<table class="columns"> + <tr> + <td colspan="2"><h4>Changing the Google Chrome chrome</h4></td> + </tr> + <tr> + <td colspan="2"> </td> + </tr> + <tr> + <td> <a href="browserAction.html">Browser Actions</a> </td> + <td> Add icons to the toolbar <em>(extensions only)</em> </td> + </tr> + <tr> + <td> <a href="notifications.html">Desktop Notifications</a> </td> + <td> Notify users of important events </td> + </tr> + <tr> + <td> <a href="omnibox.html">Omnibox</a> </td> + <td> Add a keyword to the address bar </td> + </tr> + <tr> + <td> <a href="options.html">Options Pages</a> </td> + <td> Let users customize your extension </td> + </tr> + <tr> + <td> <a href="override.html">Override Pages</a> </td> + <td> Implement your own version of standard browser pages + such as the New Tab page</td> + </tr> + <tr> + <td> <a href="pageAction.html">Page Actions</a> </td> + <td> Add temporary icons inside the address bar <em>(extensions only)</em> </td> + </tr> + <tr> + <td> <a href="themes.html">Themes</a> </td> + <td> Change the overall appearance of the browser </td> + </tr> + + <tr> + <td colspan="2"><h4>Interacting with Google Chrome in other ways</h4></td> + </tr> + <tr> + <td colspan="2"> </td> + </tr> + <tr> + <td> <a href="bookmarks.html">Bookmarks</a> </td> + <td> Create, organize, and otherwise manipulate the user's bookmarks </td> + </tr> + <tr> + <td> <a href="cookies.html">Cookies</a> </td> + <td> Explore and modify the browser's cookie system </td> + </tr> + <tr> + <td> <a href="devtools.html">Developer Tools</a> </td> + <td> Add features to Chrome Developer Tools </td> + </tr> + <tr> + <td> <a href="events.html">Events</a> </td> + <td> Detect when something interesting happens </td> + </tr> + <tr> + <td> <a href="history.html">History</a> </td> + <td> Interact with the browser's record of visited pages </td> + </tr> + <tr> + <td> <a href="tabs.html">Tabs</a> </td> + <td> Create, modify, and rearrange tabs in the browser </td> + </tr> + <tr> + <td> <a href="windows.html">Windows</a> </td> + <td> Create, modify, and rearrange windows in the browser </td> + </tr> + + <tr> + <td colspan="2"><h4>Implementing the innards of your extension</h4></td> + </tr> + <tr> + <td colspan="2"> </td> + </tr> + <tr> + <td> <a href="a11y.html">Accessibility (a11y)</a> </td> + <td> Make your extension accessible to people with disabilities </td> + </tr> + <tr> + <td> <a href="event_pages.html">Event Pages</a> </td> + <td> Put all the common code for your extension in a single place </td> + </tr> + <tr> + <td> <a href="content_scripts.html">Content Scripts</a> </td> + <td> Run JavaScript code in the context of web pages </td> + </tr> + <tr> + <td> <a href="xhr.html">Cross-Origin XHR</a> </td> + <td> Use XMLHttpRequest to send and receive data from remote servers </td> + </tr> + <tr> + <td> <a href="i18n.html">Internationalization</a> </td> + <td> Deal with language and locale </td> + </tr> + <tr> + <td> <a href="messaging.html">Message Passing</a> </td> + <td> Communicate from a content script to its parent extension, + or vice versa</td> + </tr> + <tr> + <td> <a href="permissions.html">Optional Permissions</a> </td> + <td> Modify your extension's permissions </td> + </tr> + <tr> + <td> <a href="npapi.html">NPAPI Plugins</a> </td> + <td> Load native binary code </td> + </tr> + + <tr> + <td colspan="2"><h4>Finishing and distributing your extension</h4></td> + </tr> + <tr> + <td colspan="2"> </td> + </tr> + <tr> + <td> <a href="autoupdate.html">Autoupdating</a> </td> + <td> Update extensions automatically </td> + </tr> + <tr> + <td> <a href="hosting.html">Hosting</a> </td> + <td> Host extensions on Google servers or your own </td> + </tr> + <tr> + <td> <a href="external_extensions.html">Other Deployment Options</a> </td> + <td> Distribute extensions on your network or with other software </td> + </tr> + <tr> + <td> <a href="packaging.html">Packaging</a> </td> + <td> Create a <code>.crx</code> file so you can distribute your extension </td> + </tr> +</table> diff --git a/chrome/common/extensions/docs/templates/articles/devtools.html b/chrome/common/extensions/docs/templates/articles/devtools.html new file mode 100644 index 0000000..7654cc5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/devtools.html @@ -0,0 +1,74 @@ +<h1>chrome.devtools.* APIs</h1> + +<p> +The following API modules provide support for extending +Chrome Developer Tools: +</p> + +<a name="api-list"></a> +<ul> + <li> + <a href="devtools.inspectedWindow.html">devtools.inspectedWindow</a></li><li> + <a href="devtools.network.html">devtools.network</a></li><li> + <a href="devtools.panels.html">devtools.panels</a></li> +</ul> + +<h2 id="using">How to use DevTools APIs</h2> + +<ol> + <li> + Specify the "devtools_page" field in your extension's manifest: +<pre>{ + "name": ... + "version": "1.0", + "minimum_chrome_version": "10.0", + <b>"devtools_page": "devtools.html"</b>, + ... +} +</pre> + </li> + <li> + An instance of the devtools_page specified in your extension's manifest + will be created for every Developer Tools window opened. The page may add + other extension pages as panels and sidebars to the Developer Tools window + using <a href="devtools.panels.html">devtools.panels</a> + API. + </li> + <li> + The chrome.devtools.* API modules are available only to the + pages loaded within the Developer Tools window. Content scripts and other + extension pages do not have these APIs. Thus, the APIs are available only + through the lifetime of the Developer Tools window. + </li> + <li>The APIs available to extension pages within the Developer Tools + window include all <a href="#api-list">devtools modules + listed above</a> and <a href="extension.html">chrome.extension</a> API. + Other extension APIs are not available to the Developer Tools pages, but + you may invoke them by sending a request to the background page of your + extension, similarly to how it's done in the + <a href="overview.html#contentScripts">content scripts</a>. + </li><li> + There are also some Developer Tools APIs that are still experimental. + Please refer to <a href="experimental.html">chrome.experimental.* APIs</a> + for the list of experimental APIs and guidelines on how to use them. + </li> + <li> + <a href="http://groups.google.com/group/google-chrome-developer-tools/topics">Give us feedback!</a> + Your comments and suggestions help us improve the APIs. + </li> +</ol> + +<h2 id="other">More information</h2> + +<p> +For information on the standard APIs that extensions can use, see +<a href="api_index.html">chrome.* APIs</a> and +<a href="api_other.html">Other APIs</a>. +</p> + +<h2 id="examples">Examples</h2> + +<p> +You can find examples that use Developer Tools APIs in +<a href="samples.html#devtools">Samples</a>. +</p> diff --git a/chrome/common/extensions/docs/templates/articles/docs.html b/chrome/common/extensions/docs/templates/articles/docs.html new file mode 100644 index 0000000..4525d6f --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/docs.html @@ -0,0 +1,145 @@ +<h1>Hello There!</h1> + +<p> +This documentation tells you how to write extensions +and packaged apps for the +<a href="http://www.google.com/chrome">Google Chrome browser</a>. +Because extensions came first, +the APIs and these docs say <em>extension</em> everywhere. +</p> + +<p class="caution"> +<b>Note:</b> +Unless you see a note +describing an exception for packaged apps, +everything in this documentation applies to both extensions and packaged apps. +</p> + + +<h2 id="readme"> Where to start </h2> + +<p> +Before you code, +read these: +</p> + +<dl> + <dt> <a href="getstarted.html">Getting Started (Hello, World!)</a> </dt> + <dd> Build a simple "Hello, World" extension in about 5 minutes </dd> + + <dt> <a href="overview.html">Overview</a> </dt> + <dd> Learn about the fundamental design points of the extension system </dd> +</dl> + +<p> +Also check out these: +</p> + +<ul> + <li> + <a href="devguide.html">Developer's Guide</a> + </li> + <li> + <a href="samples.html">Samples</a> + </li> + <li> + <a href="http://stackoverflow.com/questions/tagged/google-chrome-extension">Stack Overflow [google-chrome-extension] tag</a> + </li> + <li> + <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions">Group: chromium-extensions</a> + </li> + <li> + <a href="http://chrome.google.com/webstore">Chrome Web Store</a> + </li> + <li> + <a href="webstore.html">Chrome Web Store + developer documentation</a> + </li> +</ul> + +<h2 id="versions"> Doc versions </h2> +<p> +In general, you should view these pages at +<b>http://developer.chrome.com/extensions/<em><filename></em></b> +(for example, +<a href="/extensions/overview.html">http://developer.chrome.com/extensions/overview.html</a>). +However, if you need to see the very latest doc +or you're using a different version of Google Chrome +than most of the world is +(perhaps the <a href="http://dev.chromium.org/getting-involved/dev-channel">Dev channel</a>), +you might want to use a different URL +(for example, +<a href="/dev/extensions/overview.html">.../<b>dev/</b>extensions/overview.html</a>). +The following table lists the doc locations and explains how they differ. +</p> + +<p> +<table class="noborders"> + <tr> + <th> URL </th> <th> Version </th> + </tr> + <tr> + <td> + <a href="/extensions/overview.html">.../extensions/...</a> + </td> + <td> + The version you should probably be using. + This documents the most stable version of the extension API. + </td> + </tr> + <tr> + <td> + <a href="/beta/extensions/overview.html">.../<b>beta/</b>extensions/...</a> + </td> + <td> + <p> + Documentation for the Beta channel version of Google Chrome. + </p> + + <p> + <strong>Note:</strong> + APIs on the Beta channel are subject to change. + </p> + </td> + </tr> + <tr> + <td> + <a href="/dev/extensions/overview.html">.../<b>dev/</b>extensions/...</a> + </td> + <td> + <p> + Documentation for the Dev channel version of Google Chrome. + This version might also have bug fixes and feature information + that are relevant to the current doc + but haven't been integrated into it yet. + </p> + + <p> + <strong>Note:</strong> + APIs on the Dev channel are subject to change. + </p> + </td> + </tr> + <tr> + <td> + <a href="/trunk/extensions/overview.html">.../<b>trunk/</b>extensions/...</a> + </td> + <td> + The very latest documentation. + Look here if you're using + <a href="http://tools.google.com/dlpage/chromesxs">Canary</a> + or a tip-of-tree version of + <a href="http://dev.chromium.org">Chromium</a> + or if you're curious about features to come. + This version might also have bug fixes and feature information + that are relevant to the current doc + but haven't been integrated into it yet. + + <p> + <strong>Note:</strong> + The trunk version of the doc is preliminary and might have errors. + </p> + </td> + </tr> +</table> +</p> diff --git a/chrome/common/extensions/docs/templates/articles/event_pages.html b/chrome/common/extensions/docs/templates/articles/event_pages.html new file mode 100644 index 0000000..8964c5a --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/event_pages.html @@ -0,0 +1,161 @@ +<h1>Event Pages</h1> + + +<p> +Event pages are very similar to +<a href="background_pages.html">background pages</a>, +with one important difference: +event pages are loaded only when they are needed. +When the event page is not actively doing something, +it is unloaded, freeing memory and other system resources. +</p> + +<h2 id="manifest">Manifest</h2> + +<p> +Register your event page in the +<a href="manifest.html">extension manifest</a>: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"background": { + "scripts": ["eventPage.js"], + "persistent": false + }</b>, + ... +}</pre> + +<p> +Notice that without the "persistent" key, you have +a regular background page. Persistence is what differentiates +an event page from a background page. +</p> + +<h2 id="lifetime">Lifetime</h2> + +<p> +The event page is loaded when it is "needed", and unloaded +when it goes idle again. Here are some examples of things +that will cause the event page to load: +</p> +<ul> +<li>The extension is first installed or is updated to a new version +(in order to <a href="#registration">register for events</a>). +<li>The event page was listening for an event, and the event is dispatched. +<li>A content script or other extension +<a href="messaging.html">sends a message.</a> +<li>Another view in the extension (for example, a popup) calls +<code><a href="runtime.html#method-getBackgroundPage">chrome.runtime.getBackgroundPage()</a></code>. +</ul> + +<p> +Once it has been loaded, the event page will stay running +as long as it is active (for example, calling an extension +API or issuing a network request). Additionally, the +event page will not unload until all visible views (for example, +popup windows) are closed and all message ports are closed. +</p> + +<p> +You can observe the lifetime of your event page by clicking +on "View Background Pages" in Chrome's Wrench menu, or by +opening Chrome's task manager. You can see when your event +page loads and unloads by observing when an entry for your +extension appears in the list of processes. +</p> + +<p> +Once the event page has been idle a short time +(a few seconds), the +<code><a href="runtime.html#event-onSuspend">chrome.runtime.onSuspend</a></code> +event is dispatched. The event page has a few more seconds to handle this +event before it is forcibly unloaded. Note that once the event is dispatched, +new activity will not keep the event page open. +</p> + +<h2 id="registration">Event registration</h2> + +<p> +Chrome keeps track of events that an extension has added listeners +for. When it dispatches such an event, the extension's event page is +loaded. Conversely, if the extension removes all of its listeners for +an event by calling <code>removeListener</code>, Chrome will no longer +load its event page for that event. +</p> + +<p> +Because the listeners themselves only exist in the context of the +event page, you must use <code>addListener</code> each time the event +page loads; only doing so at +<code><a href="runtime.html#event-onInstalled">chrome.runtime.onInstalled</a></code> +by itself is insufficient. +</p> + +<p> +For an example of event registration in action, you can view the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gmail/">Google Mail +Checker</a> extension. +</p> + +<h2 id="transition">Convert background page to event page</h2> +<p> +Follow this checklist to convert your extension's +(persistent) background page to an event page. + +<ol> + <li>Add <code>"persistent": false</code> to your manifest as shown above. + + <li>Register to receive any events your extension is interested in + each time the event page is loaded. The event page will be loaded once + for each new version of your extension. After that it will only be + loaded to deliver events you have registered for. + + <li>If you need to do some initialization when your extension is + installed or upgraded, listen to the + <code><a href="runtime.html#event-onInstalled">chrome.runtime.onInstalled</a></code> + event. If you need to do some initialization each time the browser starts, + listen to the + <code><a href="runtime.html#event-onBrowserStartup">chrome.runtime.onBrowserStartup</a></code> + event; however, you should (in almost all cases) prefer + the <code>chrome.runtime.onInstalled</code> event. + + <li>If you need to keep runtime state in memory throughout a browser + session, use the <a href="storage.html">storage API</a> or + IndexedDB. Since the event page does not stay loaded for long, you + can no longer rely on global variables for runtime state. + + <li>Use <a href="events.html#filtered">event filters</a> to restrict + your event notifications to the cases you care about. For example, if + you listen to the <code><a href="tabs.html#event-onUpdated">tabs.onUpdated</a></code> + event, try using the + <code><a href="webNavigation.html#event-onCompleted">webNavigation.onComplete</a></code> + event with filters instead (the tabs API does not support filters). + That way, your event page will only be loaded for events that + interest you. + + <li>Listen to the + <code><a href="runtime.html#event-onSuspend">chrome.runtime.onSuspend</a></code> + event if you need to do last second cleanup before your event page + is shut down. However, we recommend persisting periodically instead. + That way if your extension crashes without receiving + <code>onSuspend</code>, no data will typically be lost. + + <li>If your extension uses <code>window.setTimeout()</code> or + <code>window.setInterval()</code>, switch to using the + <a href="alarms.html">alarms API</a> instead. DOM-based timers won't + be honored if the event page shuts down. + + <li>If your extension uses, + <code><a href="extension.html#method-getBackgroundPage">chrome.extension.getBackgroundPage()</a></code>, + switch to + <code><a href="runtime.html#method-getBackgroundPage">chrome.runtime.getBackgroundPage()</a></code> + instead. The newer method is asynchronous so that it can start the event + page if necessary before returning it. + + <li>If you're using <a href="messaging.html">message passing</a>, be sure + to close unused message ports. The event page will not shut down until all + message ports are closed. +</ol> +</p> diff --git a/chrome/common/extensions/docs/templates/articles/experimental.html b/chrome/common/extensions/docs/templates/articles/experimental.html new file mode 100644 index 0000000..6d9a086 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental.html @@ -0,0 +1,140 @@ +<h1 class="page_title">chrome.experimental.* APIs</h1> +{{^is_apps}} +<div class="doc-family extensions"> +<p> +Before you start, <strong>choose the right version of this page.</strong> +You should read either: +</p> + +<ul> + <li> <a href="http://code.google.com/chrome/extensions/trunk/experimental.html">Most recent experimental APIs</a> + <li> <a href="http://code.google.com/chrome/extensions/dev/experimental.html">Dev channel experimental APIs</a></li> +</ul> + +<p> +For information about browser versions such as +Canary (bleeding edge) and the Dev channel, see +<a href="http://www.chromium.org/getting-involved/dev-channel">Chrome Release Channels</a>. +For details about channel-specific docs, +see <a href="docs.html#versions">Doc versions</a>. +</p> +</div> +{{/is_apps}} + +<h2 id="overview"> +List of APIs +</h2> + +{{^is_apps}} +<p class="doc-family extensions"> +We'd like your <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions/topics">feedback</a> +on the following experimental APIs: +</p> +{{/is_apps}} + +<ul> + {{?is_apps}} + {{#api_list.apps.experimental}} + <li><a href="{{name}}.html">{{name}}</a></li> + {{/}} + {{:is_apps}} + {{#api_list.extensions.experimental}} + <li><a href="{{name}}.html">{{name}}</a></li> + {{/}} + {{/is_apps}} +</ul> + +{{^is_apps}} +<p class="doc-family extensions"> +Pay special attention to the following APIs, +which we expect to finalize soon: +<b>devtools</b>, +<b>infobars</b>, +<b>permissions</b>, +For examples of using the experimental APIs, see +<a href="samples.html#experimental">Samples</a>. +</p> +{{/is_apps}} + +<p class="warning"> +<b>Caution:</b> +Don't depend on these experimental APIs. +They might disappear, +and they <em>will</em> change. +Also, the Chrome Web Store doesn't allow you to +upload items that use experimental APIs. +</p> + + +<h2 id="using">How to use experimental APIs</h2> + +<ol> + {{^is_apps}} + <li class="doc-family extensions"> + Make sure you're using either + <a href="http://tools.google.com/dlpage/chromesxs">Canary</a> + (which you can use at the same time as other Chrome channels) or the +<a href="http://www.chromium.org/getting-involved/dev-channel">Dev channel</a>. + Although the experimental APIs might work in other versions, + we need your feedback on the latest incarnation of the APIs, + which you can find in Canary and on the Dev channel. + </li> + <li class="doc-family extensions"> + Using either the + <a href="http://code.google.com/chrome/extensions/trunk/experimental.html">most recent API documentation</a> (if you're using Canary) or the + <a href="http://code.google.com/chrome/extensions/dev/experimental.html">API documentation for the Dev channel</a>, + write the code for your extension. + </li> + {{/is_apps}} + <li> + Specify the "experimental" + <a href="manifest.html#permissions">permission</a> + in your manifest, like this: +<pre> +"permissions": [ + <b>"experimental"</b>, + ... +], +</pre> + </li> + <li> + Enable the experimental API in your browser. + You can do this in either of two ways: + <ul> + <li> Go to <b>chrome://flags</b>, + find "Experimental Extension APIs", + click its "Enable" link, + and restart Chrome. + From now on, + unless you return to that page and disable experimental APIs, + you'll be able to run extensions and apps that use experimental APIs. + </li> + <li> Specify the <b>--enable-experimental-extension-apis</b> flag + each time you launch the browser. + On Windows, you can do this by modifying + the properties of the shortcut that you use to launch Google Chrome. + For example: + +<pre> +<em>path_to_chrome.exe</em> <b>--enable-experimental-extension-apis</b></pre> + </li> + </ul> + </li> + + {{^is_apps}} + <li class="doc-family extension"> + <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions/topics">Give us feedback!</a> + Your comments and suggestions help us + improve the APIs and decide + which ones should move from experimental to supported. + </li> + {{/is_apps}} +</ol> + +<h2 id="other">More APIs</h2> + +<p> +For information on the standard APIs that packaged apps can use, see +<a href="api_index.html">chrome.* APIs</a> and +<a href="api_other.html">Other APIs</a>. +</p> diff --git a/chrome/common/extensions/docs/templates/articles/experimental_browsingData.html b/chrome/common/extensions/docs/templates/articles/experimental_browsingData.html new file mode 100644 index 0000000..26bd199 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_browsingData.html @@ -0,0 +1,10 @@ +<h1>experimental.browsingData</h1> + +<p> +The <code>BrowsingData</code> API is no longer experimental; +it's supported! You can read all about it at its new home: +</p> + +<blockquote> +<a href="browsingData.html">chrome.browsingData</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_contentSettings.html b/chrome/common/extensions/docs/templates/articles/experimental_contentSettings.html new file mode 100644 index 0000000..e89889b --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_contentSettings.html @@ -0,0 +1,11 @@ +<h1>experimental.chrome.contentSettings</h1> + +<p> +The <code>contentSettings</code> API is no longer experimental; +it's supported! +You can read all about it at its new home: +</p> + +<blockquote> +<a href="contentSettings.html">chrome.contentSettings</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_contextMenus.html b/chrome/common/extensions/docs/templates/articles/experimental_contextMenus.html new file mode 100644 index 0000000..cc4f5c6 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_contextMenus.html @@ -0,0 +1,11 @@ +<h1>experimental.chrome.contextMenus</h1> + +<p> +The <code>contextMenus</code> API is no longer experimental; +it's supported! +You can read all about it at its new home: +</p> + +<blockquote> +<a href="contextMenus.html">chrome.contextMenus</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_cookies.html b/chrome/common/extensions/docs/templates/articles/experimental_cookies.html new file mode 100644 index 0000000..3e060bd --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_cookies.html @@ -0,0 +1,11 @@ +<h1>experimental.chrome.cookies</h1> + +<p> +The <code>cookies</code> API is no longer experimental; +it's supported! +You can read all about it at its new home: +</p> + +<blockquote> +<a href="cookies.html">chrome.cookies</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_debugger.html b/chrome/common/extensions/docs/templates/articles/experimental_debugger.html new file mode 100644 index 0000000..8a06e06 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_debugger.html @@ -0,0 +1,10 @@ +<h1>experimental.debugger</h1> + +<p> +The <code>Debugger</code> API is no longer experimental; +it's supported! You can read all about it at its new home: +</p> + +<blockquote> +<a href="debugger.html">chrome.debugger</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_devtools.html b/chrome/common/extensions/docs/templates/articles/experimental_devtools.html new file mode 100644 index 0000000..5f6cf1f --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_devtools.html @@ -0,0 +1,8 @@ +<h1>chrome.experimental.devtools.* APIs</h1> + +<p> +Some of the Developer Tools APIs are no longer experimental. Please see <a +href="devtools.html">chrome.devtools.* APIs</a> for the guidelines on how to use +these. For the list of Developer Tools APIs that are still experimental, +please refer to <a href="experimental.html">chrome.experimental.* APIs</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_devtools_inspectedWindow.html b/chrome/common/extensions/docs/templates/articles/experimental_devtools_inspectedWindow.html new file mode 100644 index 0000000..b6ee688 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_devtools_inspectedWindow.html @@ -0,0 +1,10 @@ +<h1>experimental.devtools.inspectedWindow</h1> + +<p> +The <code>devtools.inspectedWindow</code> API is no longer experimental; +it's supported! You can read all about it at its new home: +</p> + +<blockquote> +<a href="devtools.inspectedWindow.html">chrome.devtools.inspectedWindow</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_devtools_network.html b/chrome/common/extensions/docs/templates/articles/experimental_devtools_network.html new file mode 100644 index 0000000..b8ff5f9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_devtools_network.html @@ -0,0 +1,10 @@ +<h1>experimental.devtools.network</h1> + +<p> +The <code>devtools.network</code> API is no longer experimental; +it's supported! You can read all about it at its new home: +</p> + +<blockquote> +<a href="devtools.network.html">chrome.devtools.network</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_devtools_panels.html b/chrome/common/extensions/docs/templates/articles/experimental_devtools_panels.html new file mode 100644 index 0000000..38fbe1e --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_devtools_panels.html @@ -0,0 +1,10 @@ +<h1>experimental.devtools.panels</h1> + +<p> +The <code>devtools.panels</code> API is no longer experimental; +it's supported! You can read all about it at its new home: +</p> + +<blockquote> +<a href="devtools.panels.html">chrome.devtools.panels</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_devtools_resources.html b/chrome/common/extensions/docs/templates/articles/experimental_devtools_resources.html new file mode 100644 index 0000000..b8ad01ac --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_devtools_resources.html @@ -0,0 +1,7 @@ +<h1>chrome.experimental.devtools.resources +API</h1> +<p> +The <code>experimental.devtools.resources</code> module is deprecated, use +<a href="experimental.devtools.network.html" +><code>experimental.devtools.network</code></a> instead. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_history.html b/chrome/common/extensions/docs/templates/articles/experimental_history.html new file mode 100644 index 0000000..5de0989 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_history.html @@ -0,0 +1,11 @@ +<h1>experimental.chrome.history</h1> + +<p> +The <code>history</code> API is no longer experimental; +it's supported! +You can read all about it at its new home: +</p> + +<blockquote> +<a href="history.html">chrome.history</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_inputUI.html b/chrome/common/extensions/docs/templates/articles/experimental_inputUI.html new file mode 100644 index 0000000..c8cd81c --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_inputUI.html @@ -0,0 +1,8 @@ +<h1>InputUI API</h1> + + +<p id="classSummary"> +Use the <code>chrome.experimental.input.ui</code> module to implement +input method user interface. This module is for Chrome OS only. +<a href="experimental.html">chrome.experimental.* APIs</a> page. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_privacy.html b/chrome/common/extensions/docs/templates/articles/experimental_privacy.html new file mode 100644 index 0000000..09b080b --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_privacy.html @@ -0,0 +1,10 @@ +<h1>experimental.privacy</h1> + +<p> +The <code>Privacy</code> API is no longer experimental; +it's supported! You can read all about it at its new home: +</p> + +<blockquote> +<a href="privacy.html">chrome.privacy</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_storage.html b/chrome/common/extensions/docs/templates/articles/experimental_storage.html new file mode 100644 index 0000000..f85aa4b --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_storage.html @@ -0,0 +1,10 @@ +<h1>experimental.storage</h1> + +<p> +The <code>Storage</code> API is no longer experimental; +it's supported! You can read all about it at its new home: +</p> + +<blockquote> +<a href="storage.html">chrome.storage</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_webInspector.html b/chrome/common/extensions/docs/templates/articles/experimental_webInspector.html new file mode 100644 index 0000000..0fe405f --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_webInspector.html @@ -0,0 +1,9 @@ +<h1>experimental.webInspector.* APIs</h1> + +<p> +<code>experimental.webInspector.*</code> APIs have been renamed to +<a href="experimental.devtools.html"><code>chrome.experimental.devtools.*</code> +</a>. +The old namepsace is deprecated and will be removed from future versions of +Chrome. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_webInspector_audits.html b/chrome/common/extensions/docs/templates/articles/experimental_webInspector_audits.html new file mode 100644 index 0000000..85a42bc --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_webInspector_audits.html @@ -0,0 +1,8 @@ +<h1>experimental.webInspector.audits +API</h1> +<p>The <code>experimental.webInspector.audits</code> API has been renamed to +<a href="experimental.devtools.audits.html"><code +>chrome.experimental.devtools.audits</code></a>. +The old namepsace is deprecated and will be removed from future versions of +Chrome. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_webInspector_panels.html b/chrome/common/extensions/docs/templates/articles/experimental_webInspector_panels.html new file mode 100644 index 0000000..6f6ceb8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_webInspector_panels.html @@ -0,0 +1,8 @@ +<h1>experimental.webInspector.panels +API</h1> +<p>The <code>experimental.webInspector.panels</code> API has been renamed to +<a href="experimental.devtools.panels.html"><code +>chrome.experimental.devtools.panels</code></a>. +The old namepsace is deprecated and will be removed from future versions of +Chrome. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_webInspector_resources.html b/chrome/common/extensions/docs/templates/articles/experimental_webInspector_resources.html new file mode 100644 index 0000000..b4be42d --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_webInspector_resources.html @@ -0,0 +1,8 @@ +<h1>experimental.webInspector.resources +API</h1> +<p>The <code>experimental.webInspector.resources</code> API has been renamed to +<a href="experimental.devtools.resources.html"><code +>chrome.experimental.devtools.resources</code></a>. +The old namepsace is deprecated and will be removed from future versions of +Chrome. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/experimental_webRequest.html b/chrome/common/extensions/docs/templates/articles/experimental_webRequest.html new file mode 100644 index 0000000..be95f8b --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/experimental_webRequest.html @@ -0,0 +1,15 @@ +<h1>experimental.webRequest</h1> + +<p> +The <code>WebRequest</code> API is no longer experimental; +it's supported! You can read all about it at its new home: +</p> + +<blockquote> +<a href="webRequest.html">chrome.webRequest</a> +</blockquote> + +<p> +What you see below are early outcomes of the plan to implement a declarative +version of the WebRequest API. Please ignore this until we give notice. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/external_extensions.html b/chrome/common/extensions/docs/templates/articles/external_extensions.html new file mode 100644 index 0000000..c25bf74 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/external_extensions.html @@ -0,0 +1,314 @@ +<h1>Other Deployment Options</h1> + + +<p> +Usually, users install their own extensions. +But sometimes you might want an extension +to be installed automatically. +Here are two typical cases: +</p> + +<ul> + <li> + An extension is associated with some other software, + and the extension should be installed + whenever the user installs that other software. + The extension could also be uninstalled + when the user removes that other software. + </li> + <li> + A network admin wants to install the same extensions + throughout the company. + </li> +</ul> + +<p> +An extension that's installed automatically is known as an +<em>external extension</em>. +Google Chrome supports two ways of +installing external extensions: +</p> + +<ul> + <li> Using a preferences JSON file </li> + <li> Using the Windows registry (Windows only) </li> +</ul> + +<p> +Both ways support installing an extension from a <code>.crx</code> extension +file on the user's computer. The preferences JSON file also supports installing +an extension hosted at an +<a href="autoupdate.html#H2-1">update URL</a>. +See <a href="hosting.html">hosting</a> for details on hosting an extension. +</p> + +<h2 id="prereqs">Before you begin</h2> + +<p> +First, package a +<a href="packaging.html"><code>.crx</code> file</a> +and make sure that it installs successfully. +</p> +<p> +If you wish to install from an + <a href="autoupdate.html#H2-1">update URL</a>, ensure that the extension +is properly <a href="hosting.html">hosted</a>. +</p> + +<p> +Then, before you edit the preferences file or the registry, +make a note of the following: +</p> + +<ul> + <li> The intended <b>location</b> of the extension's <code>.crx</code> file, + or the update URL from which it is served </li> + <li> The extension's <b>version</b> + (from the manifest file or the <b>chrome://extensions</b> page) </li> + <li> The extension's <b>ID</b> + (from the <b>chrome://extensions</b> page + when you've loaded the packed extension) </li> +</ul> + +<p> +The following examples assume the version is <code>1.0</code> +and the ID is <code>aaaaaaaaaabbbbbbbbbbcccccccccc</code>. +</p> + +<h2 id="preferences">Using a preferences file</h2> + +<p class="note"> +<b>Windows note:</b> +Until <a href="http://crbug.com/41902">bug 41902</a> is fixed, +you might want to use the <a href="#registry">Windows registry</a> +instead of the preferences file. +</p> + +<p class="note"> +<b>Note:</b> +Previous versions of Google Chrome used an +<code>external_extensions.json</code> file to specify which extensions to +install. This file has been deprecated in favor of individual <code>.json</code> +files, one per extension. +</p> + +<ol> +<li>If you are installing from a file, make the <code>.crx</code> extension +file available to the machine you want to install the extension on. +(Copy it to a local directory or to a network share for example, +<code>\\server\share\extension.crx</code> +or <code>/home/share/extension.crx</code>.) +</li> + +<li>Create a file with the following name in one of the folders listed below: + <code>aaaaaaaaaabbbbbbbbbbcccccccccc.json</code> where the file name (without the extension) + corresponds to your extension's ID. + The location depends on the operating system. + <dl> + <dt> Windows: </dt> + <dd> <code><em>chrome_root</em>\Application\<em>chrome_version</em>\Extensions\</code> + <br /> + Example: <code>c:\Users\Me\AppData\Local\Google\Chrome\Application\6.0.422.0\Extensions\</code> + </dd> + <dt> Mac OS X:</dt> + <dd>For a specific user: <code>~USERNAME/Library/Application Support/Google/Chrome/External Extensions/</code><br> + For all users: <code>/Library/Application Support/Google/Chrome/External Extensions/</code> + <p>The external extension file for all users is read only if every directory in the path is owned by the user <code>root</code>, has the group <code>admin</code> or <code>wheel</code>, and is not world writable. The path must also be free of symbolic links. These restrictions prevent an unprivileged user from causing extensions to be installed for all users. See <a href="#troubleshooting">troubleshooting</a> for details.</p> + <p class="note"> + <b>Note:</b> The above path for all users was added in Chrome 16. Prior versions used a different path:<br/> + <code>/Applications/Google Chrome.app/Contents/Extensions/</code> + This path was deprecated in version 17. Support was removed in version 20. Use one of the paths above instead.</p> + </dd> + + <dt> Linux: </dt> + <dd> <code>/opt/google/chrome/extensions/</code> <br> + </dd> + <dd> <code>/usr/share/google-chrome/extensions/</code> <br> + <b>Note:</b> Use <code>chmod</code> if necessary + to make sure that the <code>aaaaaaaaaabbbbbbbbbbcccccccccc.json</code> files + are world-readable. + </dd> + </dl> +</li> + +<li>If you are installing from a file, specify the extension's location and version with fields +named "external_crx" and "external_version" in the file created above. +<p> +Example: +<pre> + { + "external_crx": "/home/share/extension.crx", + "external_version": "1.0" + } +</pre> +</p> +<p class="note"> +<b>Note:</b> +You need to escape +each <code>\</code> character in the location. +For example, +<code>\\server\share\extension.crx</code> would be +<code>"\\\\server\\share\\extension.crx"</code>. +</p> +<p> +<p> +If you are installing from an update URL, specify the extension's update URL +with field name "external_update_url". +</p> +Example: +<pre>{ + "external_update_url": "http://myhost.com/mytestextension/updates.xml" +}</pre> +<p> +If you would like to install extension only for some browser locales, +you can list supported locales in field name "supported_locale". Locale may +specify parent locale like "en", in this case the extension will be +installed for all English locales like "en-US", "en-GB", etc. +If another browser locale is selected that is not supported by the extension, +the external extensions will be uninstalled. If "supported_locales" list +is missing, the extension will be installed for any locale. +</p> +Example: +<pre>{ + "external_update_url": "http://myhost.com/mytestextension/updates.xml", + "supported_locales": [ "en", "fr", "de" ] +}</pre> +</li> +<li>Save the JSON file. </li> +<li>Launch Google Chrome and go to <b>chrome://extensions</b>; +you should see the extension listed. </li> +</ol> + +<h3 id="troubleshooting">Troubleshooting Mac OS permissions problems</h3> + +<p>On Mac OS, the external extensions files for all users are only read if file system permissions prevent unprivileged users from changing it. If you do not see external extensions installed when Chrome is launched, there may be a permissions problem with the external extensions preferences files. To see if this is the problem, follow these steps:</p> + +<ol> + <li> Launch the Console program. You can find it under /Applications/Utilities/Console. </li> + <li> If the leftmost icon in the Console says "Show Log List", click that icon. A second column appears at the left. </li> + <li> Click "Console Messages" in the left pane. </li> + <li> Search for the string <b>Can not read external extensions</b>. If there is a problem reading the external extensions files, you will see an error message. Look for another error message directly above it, which should explain the issue. For example, if you see the following error: + "Path /Library/Application Support/Google/Chrome is owned by the wrong group", you need to use <code>chgrp</code> or the Finder's Get Info dialog to change the directory's group owner to the Administrator group.</li> + <li> After fixing the issue, relaunch Chrome. Test that the external extension is now installed. It is possible that one permissions error keeps Chrome from detecting a second error. If the external extension was not installed, repeat these steps until you do not see an error in the Console application. +</ol> + +<h2 id="registry">Using the Windows registry</h2> + +<ol> +<li>Make the <code>.crx</code> extension file available +to the machine you want to install the extension on. +(Copy it to a local directory or to a network share — +for example, <code>\\server\share\extension.crx</code>.) +</li> +<li>Find or create the following key in the +registry: +<ul> + <li> 32-bit Windows: <code>HKEY_LOCAL_MACHINE\Software\Google\Chrome\Extensions</code> </li> + <li> 64-bit Windows: <code>HKEY_LOCAL_MACHINE\Software\Wow6432Node\Google\Chrome\Extensions</code> </li> +</ul> +</li> + +<li>Create a new key (folder) +under the <b>Extensions</b> key with the +same name as the ID of your extension +(for example, <code>aaaaaaaaaabbbbbbbbbbcccccccccc</code>). +</li> +<li>Create two string values (<code>REG_SZ</code>) named "path" and "version", + and set them to the extension's location and version. + For example: +<ul> + <li>path: <code>\\server\share\extension.crx</code> </li> + <li>version: <code>1.0</code> </li> +</ul> +</li> +<li>Launch the browser and go to +<b>chrome://extensions</b>; you should +see the extension listed. </li> +</ol> + +<h2 id="updating">Updating and uninstalling</h2> + +<p>Google Chrome scans the metadata entries +in the preferences and registry +each time the browser starts, and makes +any necessary changes to the installed +external extensions. </p> + +<p>To update your extension to a new version, +update the file, and then update the version +in the preferences or registry. </p> + +<p>To uninstall your extension +(for example, if your software is uninstalled), +remove your preference file (aaaaaaaaaabbbbbbbbbbcccccccccc.json) +or the metadata from the registry. </p> + +<h2 id="faq">FAQ</h2> + +<p> +This section answers common questions about external extensions. +</p> + +<br> + +<p><b>Can I specify a URL as a path to the external extension?</b> </p> +<p>Yes, if you use a <a href="#preferences">preferences JSON</a> file. The +extension must be hosted as explained in <a href="hosting.html">hosting</a>. +Use the "external_update_url" property to point to an +<a href="autoupdate.html#H2-2">update manifest</a> that has the URL for your +extension.</p> + +<br> + +<p><b>What are some common mistakes when installing with the preferences +file?</b></p> +<ul> + <li> + Not specifying the same id/version + as the one listed in the <code>.crx</code> </li> + <li> + The .json file (<code>aaaaaaaaaabbbbbbbbbbcccccccccc.json</code>) is in + the wrong location or the ID specified does not match the extension ID. + <li> + Syntax error in JSON file + (forgetting to separate entries with comma or + leaving a trailing comma somewhere) </li> + <li> + JSON file entry points to the wrong path + to the <code>.crx</code> (or path specified but no filename) </li> + <li> + Backslashes in UNC path not escaped + (for example, <code>"\\server\share\file"</code> is wrong; + it should be <code>"\\\\server\\share\\extension"</code>) </li> + <li> + Permissions problems on a network share </li> +</ul> + +<br> + +<p><b>What are some common mistakes when installing with the registry?</b> </p> +<ul> + <li>Not specifying the same id/version + as the one listed in the <code>.crx</code> </li> + <li>Key created in the wrong location in the registry </li> + <li>Registry entry points to the wrong path to the <code>.crx</code> file + (or path specified but no filename) </li> + <li>Permissions problems on a network share </li> +</ul> + +<br> + +<p><b>What if the user uninstalls the extension?</b> </p> +<p>If the user uninstalls the extension through the UI, it will no +longer be installed or updated on each startup. In other words, the +external extension is blacklisted. </p> + +<br> + +<p><b>How do I get off the blacklist?</b> </p> +<p>If the user uninstalls your extension, you should respect that +decision. However, if you (the developer) accidentally uninstalled +your extension through the UI, +you can remove the blacklist tag +by installing the extension normally +through the UI, and then uninstalling it. </p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/faq.html b/chrome/common/extensions/docs/templates/articles/faq.html new file mode 100644 index 0000000..9cec4d9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/faq.html @@ -0,0 +1,486 @@ +<h1>Frequently Asked Questions</h1> + + +<!-- --> + +<p> +If you don't find an answer to your question here, +try the +<a href="http://code.google.com/chrome/webstore/faq.html">Chrome Web Store FAQ</a>, the +<a href="http://stackoverflow.com/questions/tagged/google-chrome-extension">[google-chrome-extension] tag on Stack Overflow</a>, the +<a href="http://groups.google.com/a/chromium.org/group/chromium-extensions">group</a>, or the +<a href="http://www.google.com/support/chrome_webstore/">store help</a>. +</p> + +<div id="faq-TOC"> + <h4>General</h4> + <ul> + <li><a href="#faq-gen-01">What are Google Chrome Extensions?</a></li> + <li><a href="#faq-dev-01">How can I set up Chrome for extension development?</a></li> + <li><a href="#faq-gen-02">What technologies are used to write extensions for Chrome?</a></li> + <li><a href="#faq-gen-03">Are extensions fetched from the web every time the browser is loaded?</a></li> + <li><a href="#faq-dev-14">How do I determine which version of Chrome is deployed to which channel?</a></li> + </ul> + <h4>Capabilities</h4> + <ul> + <li><a href="#faq-dev-02">Can extensions make cross-domain Ajax requests?</a></li> + <li><a href="#faq-dev-03">Can extensions use 3rd party web services?</a></li> + <li><a href="#faq-dev-07">Can extensions encode/decode JSON data?</a></li> + <li><a href="#faq-dev-08">Can extensions store data locally?</a></li> + <li><a href="#faq-dev-04">Can extensions use OAuth?</a></li> + <li><a href="#faq-dev-06">Can extensions load DLLs?</a></li> + <li><a href="#faq-dev-05">Can extensions create UI outside of the rendered web page?</a></li> + <li><a href="#faq-interact-chrome">Can extensions listen to clicks on Chrome tabs and navigation buttons?</a> + <li><a href="#faq-dev-11">Can two extensions communicate with each other?</a></li> + <li><a href="#faq-dev-13">Can extensions use Google Analytics?</a></li> + <li><a href="#faq-dev-15">Can extensions modify chrome:// URLs?</a></li> + <li><a href="#faq-open-popups">Can extensions open browser/page action popups without user interaction?</a></li> + <li><a href="#faq-persist-popups">Can extensions keep popups open after the user clicks away from them?</a></li> + <li><a href="#faq-lifecycle-events">Can extensions be notified when they are installed/uninstalled?</a></li> + </ul> + <h4>Development</h4> + <ul> + <li><a href="#faq-building-ui">How do I build a UI for my extension?</a> + <li><a href="#faq-dev-09">How much data can I store in localStorage?</a></li> + <li><a href="#faq-dev-10">How do I create an options menu for my application?</a></li> + <li><a href="#faq-dev-12">What debugging tools are available to extension developers?</a></li> + <li><a href="#faq-dev-16">Why do wildcard matches not work for top level domains (TLDs)?</a></li> + <li><a href="#faq-management">Why does the management API not fire events when my extension is installed/uninstalled?</a></li> + <li><a href="#faq-firstrun">How can an extension determine whether it is running for the first time?</a></li> + </ul> + <h4>Features and bugs</h4> + <ul> + <li><a href="#faq-fea-01">I think I've found a bug! How do I make sure it gets fixed?</a></li> + <li><a href="#faq-fea-02">I have a feature request! How can I report it?</a></li> + </ul> +</div> + +<h2>General</h2> + +<h3 id="faq-gen-01">What are Google Chrome Extensions?</h3> +<p> + Google Chrome Extensions are applications that run inside the + Chrome browser and provide additional functionality, integration with third + party websites or services, and customized browsing experiences. +</p> + +<h3 id="faq-dev-01">How can I set up Chrome for extension development?</h3> +<p> + As long as you are using a version of Chrome that supports + extensions, you already have everything you need to start writing an + extension of your own. + You can start by turning on Developer mode. + </p> + + <p> + Click the wrench icon + <img src="{{static}}/images/toolsmenu.gif" height="29" width="29" alt="" + class="nomargin" /> + and select <b>Extensions</b> from the <b>Tools</b> menu. + If there's a "+" next to "Developer mode", + click the "+" so it turns into a "-". + Now you can reload extensions, + load an unpacked directory of files as if it were a packaged extension, + and more. For a complete tutorial, see + <a href="http://code.google.com/chrome/extensions/getstarted.html">Getting Started</a>. +</p> + +<h3 id="faq-gen-02">What technologies are used to write extensions for Chrome?</h3> +<p> + Extensions are written using the same standard web + technologies that developers use to create websites. HTML is used as a + content markup language, CSS is used for styling, and JavaScript for + scripting. Because Chrome supports HTML5 and CSS3, developers can + use the latest open web technologies such as canvas and CSS animations in + their extensions. Extensions also have access to several + <a href="http://code.google.com/chrome/extensions/api_other.html">JavaScript APIs</a> + that help perform functions like JSON encoding and interacting with the + browser. +</p> + + +<h3 id="faq-gen-03">Are extensions fetched from the web every time the browser is loaded?</h3> +<p> + Extensions are downloaded by the Chrome browser upon install, and + are subsequently run off of the local disk in order to speed up + performance. However, if a new version of the extension is pushed online, + it will be automatically downloaded in the background to any users who + have the extension installed. Extensions may also make requests for remote + content at any time, in order to interact with a web service or pull new + content from the web. +</p> + +<h3 id="faq-dev-14">How do I determine which version of Chrome is deployed to which channel?</h3> +<p> + To determine which version of Chrome is currently available on each + of the different platforms, visit + <a href="http://omahaproxy.appspot.com">omahaproxy.appspot.com</a>. On that + site you will see data in a format similar to: +</p> + +<pre>cf,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +cf,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +cf,stable,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +linux,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +linux,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +linux,stable,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +mac,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +mac,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +mac,stable,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +win,canary,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +win,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +win,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +win,stable,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +cros,dev,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,##### +cros,beta,#.#.###.#,#.#.###.#,mm/dd/yy,mm/dd/yy,#####,#####,#####</pre> + +<p> + Each line represents information about a different platform and channel + combination. The + listed platforms are <code>cf</code> (Google Chrome Frame), + <code>linux</code>, <code>mac</code>, <code>win</code>, and + <code>cros</code> (Google Chrome OS). The listed + channels are <code>canary</code>, <code>dev</code>, <code>beta</code>, + and <code>stable</code>. + The two four-part numbers after the channel represent the current and previous + versions of Chrome deployed to that platform-channel + combination. The rest of the information is metadata about when the releases + were first pushed, as well as revision numbers associated with each build. +</p> + + +<h2>Capabilities</h2> + +<h3 id="faq-dev-02">Can extensions make cross-domain Ajax requests?</h3> +<p> + Yes. Extensions can make cross-domain requests. See + <a href="http://code.google.com/chrome/extensions/xhr.html">this page</a> + for more information. +</p> + +<h3 id="faq-dev-03">Can extensions use 3rd party web services?</h3> +<p> + Yes. Extensions are capable of making cross-domain Ajax + requests, so they can call remote APIs directly. APIs that provide data + in JSON format are particularly easy to use. +</p> + +<h3 id="faq-dev-07">Can extensions encode/decode JSON data?</h3> +<p> + Yes, because V8 (Chrome's JavaScript engine) supports + JSON.stringify and JSON.parse natively, you may use these functions in your + extensions + <a href="http://json.org/js.html">as described here</a> without including + any additional JSON libraries in your code. +</p> + +<h3 id="faq-dev-08">Can extensions store data locally?</h3> +<p> + Yes, extensions can use <a href="http://dev.w3.org/html5/webstorage/">localStorage</a> + to store string data permanently. Using Chrome's built-in JSON + functions, you can store complex data structures in localStorage. For + extensions that need to execute SQL queries on their stored data, + Chrome implements + <a href="http://dev.w3.org/html5/webdatabase/">client side SQL databases</a>, + which may be used as well. +</p> + +<h3 id="faq-dev-04">Can extensions use OAuth?</h3> +<p> + Yes, there are extensions that use OAuth to access remote data + APIs. Most developers find it convenient to use a + <a href="http://unitedheroes.net/OAuthSimple/js/OAuthSimple.js">JavaScript OAuth library</a> + in order to simplify the process of signing OAuth requests. +</p> + +<h3 id="faq-dev-06">Can extensions load DLLs?</h3> +<p> + Yes, using the <a href="npapi.html">NPAPI interface</a>. + Because of the possibility for abuse, though, we will review your extension + before hosting it in the Chrome Web Store. +</p> + +<h3 id="faq-dev-05">Can extensions create UI outside of the rendered web page?</h3> +<p> + Yes, your extension may add buttons to the Chrome browser's user interface. + See <a href="browserAction.html">browser actions</a> and + <a href="pageAction.html">page actions</a> for more information. +</p> +<p> + An extension may also create popup notifications, which exist outside of the + browser window. See the <a href="notifications.html">desktop + notifications</a> documentation for more details. +</p> + +<h3 id="faq-interact-chrome">Can extensions listen to clicks on Chrome tabs and + navigation buttons?</h3> +<p> + No. Extensions are limited to listening to the events described in the <a + href="api_index.html">API documentation</a>. +</p> + +<h3 id="faq-dev-11">Can two extensions communicate with each other?</h3> +<p> + Yes, extensions may pass messages to other extensions. See the + <a href="messaging.html#external">message passing documentation</a> + for more information. +</p> + +<h3 id="faq-dev-13">Can extensions use Google Analytics?</h3> +<p> + Yes, since extensions are built just like websites, they can use + <a href="http://www.google.com/analytics/">Google Analytics</a> to track + usage. However, we strongly advise you to modify the tracking code to pull + an HTTPS version of the Google Analytics library. See + <a href="tut_analytics.html">this tutorial</a> for more information on doing + this. +</p> + +<h3 id="faq-dev-15">Can extensions modify chrome:// URLs?</h3> +<p> + No. The extensions APIs have been designed to minimize backwards + compatibility issues that can arise when new versions of the browser are + pushed. Allowing content scripts on <code>chrome://</code> + URLs would mean that developers would begin to rely on the DOM, CSS, and + JavaScript of these pages to stay the same. In the best case, these pages + could not be updated as quickly as they are being updated right now. + In the worst case, it could mean that an update to one + of these pages could cause an extension to break, causing key parts of the + browser to stop working for users of that extension. +</p> + +<p> + The reason that <a href="override.html">replacing the content</a> + hosted at these URLs entirely is + allowed is because it forces an extension developer to implement all of the + functionality they want without depending on the browser's internal implementation + to stay the same. +</p> + +<h3 id="faq-open-popups">Can extensions open browser/page action popups without + user interaction?</h3> +<p> + No, popups can only be opened if the user clicks on the corresponding page or + browser action. An extension cannot open its popup programatically. +</p> + +<h3 id="faq-persist-popups">Can extensions keep popups open after the user + clicks away from them?</h3> +<p> + No, popups automatically close when the user focuses on some portion of the + browser outside of the popup. There is no way to keep the popup open after + the user has clicked away. +</p> + +<h3 id="faq-lifecycle-events">Can extensions be notified when they are + installed/uninstalled?</h3> +<p> + No, there are no events an extension can listen to in order to determine + whether it has been installed or uninstalled. However, an extension can + determine when it has been run for the first time. See <a + href="#faq-firstrun">this FAQ entry</a> for information. +</p> + + +<h2>Development</h2> + + +<h3 id="faq-building-ui">How do I build a UI for my extension?</h3> +<p> + Extensions use HTML and CSS to define their user interfaces, so you can use + standard form controls to build your UI, or style the interface with CSS, + as you would a web page. Additionally, extensions can add + <a href="#faq-dev-05">some limited UI elements to Chrome itself.</a> +</p> + +<h3 id="faq-dev-09">How much data can I store in localStorage?</h3> +<p> + Extensions can store up to 5MB of data in localStorage. +</p> + +<h3 id="faq-dev-10">How do I create an options menu for my application?</h3> +<p> + You can let users set options for your extension by creating an + <a href="http://code.google.com/chrome/extensions/trunk/options.html">options page</a>, + which is a simple HTML page that will be loaded when a user clicks the + "options" button for your extension. This page can read and write settings + to localStorage, or even send options to a web server so that they can be + persisted across browsers. +</p> + +<h3 id="faq-dev-12">What debugging tools are available to extension developers?</h3> +<p> + Chrome's built-in developer tools can be used to debug extensions + as well as web pages. See this + <a href="http://code.google.com/chrome/extensions/tut_debugging.html ">tutorial on debugging extensions</a> + for more information. +</p> + +<h3 id="faq-dev-16">Why do wildcard matches not work for top level domains + (TLDs)?</h3> +<p> + You cannot use wildcard match patterns like <code>http://google.*/*</code> + to match TLDs (like <code>http://google.es</code> and + <code>http://google.fr</code>) due to the + complexity of actually restricting such a match to only the desired domains. +</p> +<p> + For the example of <code>http://google.*/*</code>, the Google domains would + be matched, but so would <code>http://google.someotherdomain.com</code>. + Additionally, many sites do not own all of the TLDs for their + domain. For an example, assume you want to use + <code>http://example.*/*</code> to match <code>http://example.com</code> and + <code>http://example.es</code>, but <code>http://example.net</code> is a + hostile site. If your extension has a bug, the hostile site could potentially + attack your extension in order to get access to your extension's increased + privileges. +</p> +<p> + You should explicitly enumerate the TLDs that you wish to run + your extension on. +</p> + +<h3 id="faq-management">Why does the management API not fire events when my + extension is installed/uninstalled?</h3> +<p> + The <a href="management.html">management API</a> was intended to help create + new tab page replacement extensions. It was not intended to fire + install/uninstall events for the current extension. +</p> + +<h3 id="faq-firstrun">How can an extension determine whether it is running for + the first time?</h3> +<p> + An extension can check to see whether it is running for the first time by + checking for the presence of a value in localStorage, and writing the value if + it does not exist. For example: +</p> + +<pre>var firstRun = (localStorage['firstRun'] == 'true'); +if (!firstRun) { + localStorage['firstRun'] = 'true'; +}</pre> + +<p> + Note that this check should be run in a background page, not a content script. +</p> + + +<h2>Features and bugs</h2> + + +<h3 id="faq-fea-01">I think I've found a bug! How do I make sure it gets + fixed?</h3> +<p> + While developing an extension, you may find behavior that does not + match the extensions documentation and may be the result of a bug in + Chrome. The best thing to do is to make sure an appropriate issue + report is filed, and the Chromium team has enough information to reproduce + the behavior. +</p> + +<p>The steps you should follow to ensure this are:</p> + +<ol> + <li> + Come up with a <em>minimal</em> test extension that demonstrates the issue + you wish to report. This extension should have as little code as possible + to demonstrate the bug—generally this should be 100 lines of + code or less. Many times, developers find that they cannot reproduce their + issues this way, which is a good indicator that the bug is in their own + code. + </li> + <li> + Search the issue tracker at + <a href="http://www.crbug.com">http://www.crbug.com</a> to see whether + someone has reported a similar issue. Most issues related to + extensions are filed under <strong>Feature=Extensions</strong>, so to + look for an extension bug related to the + chrome.tabs.executeScript function (for example), search for + "<code>Feature=Extensions Type=Bug chrome.tabs.executeScript</code>", + which will give you + <a href="http://code.google.com/p/chromium/issues/list?can=2&q=Feature%3DExtensions+Type%3DBug+chrome.tabs.executeScript&colspec=ID+Stars+Pri+Area+Feature+Type+Status+Summary+Modified+Owner+Mstone+OS&x=mstone&y=area&cells=tiles"> + this list of results</a>. + </li> + <li> + If you find a bug that describes your issue, click the star icon to be + notified when the bug receives an update. <em>Do not respond to the + bug to say "me too" or ask "when will this be fixed?"</em>; such updates + can cause hundreds of emails to be sent. Add a comment only if you have + information (such as a better test case or a suggested fix) that is likely + to be helpful. + </li> + <li> + If you found no appropriate bug to star, file a new issue report at + <a href="http://new.crbug.com">http://new.crbug.com</a>. Be as explicit + as possible when filling out this form: choose a descriptive title, + explain the steps to reproduce the bug, and describe the expected and + actual behavior. Attach your test example to the report and add + screenshots if appropriate. The easier your report makes it for others + to reproduce your issue, the greater chance that your bug will be fixed + promptly. + </li> + <li> + Wait for the bug to be updated. Most new bugs are triaged within a week, + although it can sometimes take longer for an update. <em>Do not reply + to the bug to ask when the issue will be fixed.</em> If your bug has not + been modified after two weeks, please post a message to the + <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions/topics"> + discussion group</a> with a link back to your bug. + </li> + <li> + If you originally reported your bug on the discussion group and were + directed to this FAQ entry, reply to your original thread with a link + to the bug you starred or reported. This will make it easier for others + experiencing the same issue to find the correct bug. + </li> +</ol> + +<h3 id="faq-fea-02">I have a feature request! How can I report it?</h3> + +<p>If you identify a feature (especially if it's related to an experimental + API) that could be added to improve the extension development experience, + make sure an appropriate request is filed in the issue tracker.</p> + +<p>The steps you should follow to ensure this are:</p> + +<ol> + <li> + Search the issue tracker at + <a href="http://www.crbug.com">http://www.crbug.com</a> to see whether + someone has requested a similar feature. Most requests related to + extensions are filed under <strong>Feature=Extensions</strong>, so to + look for an extension feature request related to keyboard shortcuts + (for example), search + for "<code>Feature=Extensions Type=Feature shortcuts</code>", + which will give you + <a href="http://code.google.com/p/chromium/issues/list?can=2&q=Feature%3DExtensions+Type%3DFeature+shortcuts&colspec=ID+Stars+Pri+Area+Feature+Type+Status+Summary+Modified+Owner+Mstone+OS&x=mstone&y=area&cells=tiles"> + this list of results</a>. + </li> + <li> + If you find a ticket that matches your request, click the star icon to be + notified when the bug receives an update. <em>Do not respond to the + bug to say "me too" or ask "when will this be implemented?"</em>; such + updates can cause hundreds of emails to be sent. + </li> + <li> + If you found no appropriate ticket to star, file a new request at + <a href="http://new.crbug.com">http://new.crbug.com</a>. Be as detailed + as possible when filling out this form: choose a descriptive title + and explain exactly what feature you would like and how you plan to use it. + </li> + <li> + Wait for the ticket to be updated. Most new requests are triaged within a + week, although it can sometimes take longer for an update. <em>Do not reply + to the ticket to ask when the feature will be added.</em> If your + ticket has not been modified after two weeks, please post a message to the + <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions/topics"> + discussion group</a> with a link back to your request. + </li> + <li> + If you originally reported your request on the discussion group and were + directed to this FAQ entry, reply to your original thread with a link + to the ticket you starred or opened. This will make it easier for others + with the same request to find the correct ticket. + </li> +</ol>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/first_app.html b/chrome/common/extensions/docs/templates/articles/first_app.html new file mode 100644 index 0000000..7a31467 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/first_app.html @@ -0,0 +1,166 @@ +<meta name="doc-family" content="apps"> +<h1>Create Your First App</h1> + + +<p> +This tutorial walks you through creating your first packaged app. +Packaged apps are structured similarly to extensions +so current developers will recognize the manifest and packaging methods. +When you're done, +you'll just need to produce a zip file of your code and assets +in order to <a href="publish_app.html">publish</a> your app. +</p> + +<p> +A packaged app contains these components: +</p> + +<ul> + <li>The <strong>manifest</strong> tells Chrome about your app, what it is, + how to launch it and the extra permissions that it requires.</li> + <li>The <strong>background script</strong> is used to create the event page + responsible for managing the app life cycle.</li> + <li>All code must be included in the package. This includes HTML, JS, CSS + and Native Client modules.</li> + <li>All <strong>icons</strong> and other assets must be included + in the package as well.</li> +</ul> + +<p class="note"> +<b>API Samples: </b> +Want to play with the code? +Check out the +<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/hello-world">hello-world</a> +sample. +</p> + +<h2 id="one">Step 1: Create the manifest</h2> + +<p> +First create your <code>manifest.json</code> file +(<a href="manifest.html">Formats: Manifest Files</a> +describes this manifest in detail): +</p> + +<pre> +{ + "name": "Hello World!", + "description": "My first packaged app.", + "version": "0.1", + "app": { + "background": { + "scripts": ["background.js"] + } + }, + "icons": { "16": "calculator-16.png", "128": "calculator-128.png" } +} +</pre> + +<p class="note"> +<b>Important:</b> +Packaged apps <b>must</b> use +<a href="manifestVersion.html">manifest version 2</a>. +</p> + +<h2 id="two">Step 2: Create the background script</h2> + +<p> +Next create a new file called <code>background.js</code> +with the following content: +</p> + +<pre> +chrome.app.runtime.onLaunched.addListener(function() { + chrome.app.window.create('window.html', { + 'width': 400, + 'height': 500 + }); +}); +</pre> + +<p> +In the above sample code, +the <a href="app_lifecycle.html#lifecycle">onLaunched event</a> +will be fired when the user starts the app. +It then immediately opens a window for the app of the specified width and height. +Your background script may contain additional listeners, +windows, post messages, and launch data, +all of which are used by the event page to manage the app. +</p> + +<h2 id="three">Step 3: Create a window page</h2> + +<p> +Create your <code>window.html</code> file: +</p> + +<pre> +<!DOCTYPE html> +<html> + <head> + </head> + <body> + <div>Hello, world!</div> + </body> +</html> +</pre> + +<h2 id="four">Step 4: Create the icons</h2> + +<p> +Copy these icons to your app folder: +</p> + +<ul> + <li><a href="{{static}}/images/calculator-16.png">calculator-16.png</a></li> + <li><a href="{{static}}/images/calculator-128.png">calculator-128.png</a></li> +</ul> + +<h2 id="five">Step 5: Launch your app</h2> + +<h3>Enable flags</h3> + +<p> +Many of the packaged apps APIs are still experimental, +so you should enable experimental APIs +so that you can try them out: +</p> + +<ul> + <li>Go to <b>chrome://flags</b>.</li> + <li>Find "Experimental Extension APIs", + and click its "Enable" link.</li> + <li>Restart Chrome.</li> +</ul> + +<h3>Load your app</h3> + +<p> +To load your app, +bring up the apps and extensions management page +by clicking the wrench icon +<img src="{{static}}/images/toolsmenu.gif" width="29" height="29" alt="" + style="margin-top:0" /> +and choosing <b>Tools > Extensions</b>. +</p> + +<p> +Make sure the <b>Developer mode</b> +checkbox has been selected. +</p> + +<p> +Click the <b>Load unpacked extension</b> button, +navigate to your app's folder +and click <b>OK</b>. +</p> + +<h3>Open new tab and launch</h3> + +<p> +Once you've loaded your app, +open a New Tab page +and click on your new app icon. +</p> + +<p class="backtotop"><a href="#top">Back to top</a></p> diff --git a/chrome/common/extensions/docs/templates/articles/getstarted.html b/chrome/common/extensions/docs/templates/articles/getstarted.html new file mode 100644 index 0000000..6659bf6 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/getstarted.html @@ -0,0 +1,204 @@ +<h1>Tutorial: Getting Started (Hello, World!)</h1> + + +<p> + This tutorial walks you through creating a simple extension. You'll add an + icon to Google Chrome that, when clicked, displays an automatically generated + page. The icon and page will look something like this: +</p> + +<img src="{{static}}/images/hello-world-small.png" + width="300" + height="221" + alt="a window with a grid of images related to 'Hello World'"> + +<p> + You can develop extensions using any release of Google Chrome, on Windows, + Mac, or Linux. Extensions you develop on one platform should run without + change on every platform Chrome supports. +</p> + +<h2 id="load">Create and load an extension</h2> + +<p> + The extension we'll walk through creating here is a + <a href="browserAction.html">Browser Action</a>, which adds a button to + Chrome's toolbar whose behavior you can control. +</p> + +<ol> + <li> + Create a folder somewhere on your computer to contain your extension's code. + </li> + <li> + <p> + Inside your extension's folder, create a text file called + <strong><code>manifest.json</code></strong>, and fill it with the + following code: + </p> + <pre>{ + "name": "My First Extension", + "version": "1.0", + "manifest_version": 2, + "description": "The first extension that I made.", + "browser_action": { + "default_icon": "icon.png" + }, + "permissions": [ + "http://api.flickr.com/" + ] +}</pre> + </li> + <li> + <p>Copy this icon to the same folder:</p> + <div style="width: 150px; text-align: center;"> + <a href='../examples/tutorials/getstarted/icon.png' + download='icon'> + <img src='../examples/tutorials/getstarted/icon.png' + width='19' + height='19' + alt='' + style='display: block; margin: 0.25em auto;'> + Download icon.png + </a> + </div> + </li> + <li id="load-ext"> + <p>Load the extension.</p> + <ol type="a"> + <li style="margin-top:0" /> + Bring up the extensions management page + by clicking the wrench icon + <img src="{{static}}/images/toolsmenu.gif" width="29" height="29" alt="" + style="margin-top:0" /> + and choosing <b>Tools > Extensions</b>. + </li> + + <li> + If <b>Developer mode</b> has a + by it, + click the + to add developer information to the page. + The + changes to a -, + and more buttons and information appear. + </li> + + <li> + Click the <b>Load unpacked extension</b> button. + A file dialog appears. + </li> + + <li> + In the file dialog, + navigate to your extension's folder + and click <b>OK</b>. + </li> + </ol> </li> + </ol> + +<p> +If your extension is valid, +its icon appears next to the address bar, +and information about the extension +appears in the extensions page, +as the following screenshot shows. +</p> + +<p> +<a href="{{static}}/images/load_after.png"><img + src="{{static}}/images/load_after_small.png" + width="300" height="132" /></a> +</p> + +<h2 id="code">Add code to the extension</h2> +<p> + In this step, you'll make your extension <em>do</em> something besides just + look good. +</p> + +<ol> + <li> + <p>Edit <code>manifest.json</code> to add the following line:</p> + <pre>... + "browser_action": { + "default_icon": "icon.png"<b>, + "default_popup": "popup.html"</b> + }, + ...</pre> + + <p> + Inside your extension's folder, create two text files called + <strong><code>popup.html</code></strong> and + <strong><code>popup.js</code></strong>. Add the following code to + these files: + </p> + <blockquote> + <a href="../examples/tutorials/getstarted/popup.html" + target="_blank">HTML code (popup.html)</a> and + <a href="../examples/tutorials/getstarted/popup.js" + target="_blank">JavaScript code (popup.js)</a> for hello_world</a> </blockquote> + </li> + <li> + Return to the extensions management page, + and click the <b>Reload</b> button + to load the new version of the extension.</li> + <li>Click the extension's icon. + A popup should appear that displays the contents of + <code>popup.html</code>. </li> +</ol> +<p> It should look something like this:</p> + +<img src="{{static}}/images/hello-world.png" + width="500" height="369" + alt="a popup with a grid of images related to HELLO WORLD" /> + +<p> If you don't see the popup, +try the instructions again, +following them exactly. +Don't try loading an HTML file that isn't in the extension's folder — +it won't work! </p> + +<h2 id="summary">Now what?</h2> + + + +<p> +Here are some suggestions for what to read next: +</p> + +<ul> + <li> + The <a href="overview.html">Overview</a>, + which has important conceptual and practical information + </li> + <li> + The + <a href="tut_debugging.html">debugging tutorial</a>, + which starts where this tutorial leaves off + </li> + <li> + The <a href="hosting.html">hosting</a> page, + which tells you about options for distributing your extension + </li> +</ul> + +<p> +If you don't feel like reading, try these: +</p> +<ul> + <li> + Keep up to date with the latest news: + <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions/subscribe">subscribe to chromium-extensions</a> + </li> + <li> + Ask a question tagged [google-chrome-extension] on + <a href="http://stackoverflow.com/questions/tagged/google-chrome-extension">Stack Overflow</a> + </li> + <li> + Look at some + <a href="samples.html">sample extensions</a> + </li> + <li> + Watch some + <a href="http://www.youtube.com/view_play_list?p=CA101D6A85FE9D4B">videos</a>, such as + <a href="http://www.youtube.com/watch?v=e3McMaHvlBY&feature=PlayList&p=CA101D6A85FE9D4B&index=3">How to build an extension</a> + </li> +</ul>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/hosting.html b/chrome/common/extensions/docs/templates/articles/hosting.html new file mode 100644 index 0000000..636e857 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/hosting.html @@ -0,0 +1,84 @@ +<h1>Hosting</h1> + +<p> +This page tells you how to host <code>.crx</code> files +on your own server. +If you distribute your extension, app, or theme solely through the +<a href="http://chrome.google.com/webstore">Chrome Web Store</a>, +you don't need this page. +Instead, consult the +<a href="http://www.google.com/support/chrome_webstore/">store help</a> and +<a href="http://code.google.com/chrome/webstore/index.html">developer documentation</a>. +</p> + +<p> +By convention, extensions, +installable web apps, and themes are served—whether +by the Chrome Web Store or by a custom server—as +<code>.crx</code> files. +When you upload a ZIP file with the +<a href="https://chrome.google.com/webstore/developer/dashboard">Chrome Developer Dashboard</a>, +the dashboard creates the <code>.crx</code> file for you. +</p> + +<p> +If you aren't publishing using the dashboard, +you need to create the <code>.crx</code> file yourself, +as described in <a href="packaging.html">Packaging</a>. +You can also specify +<a href="autoupdate.html">autoupdate</a> information to ensure that +your users will have the latest copy of the <code>.crx</code> file. +</p> + +<p> +A server that hosts <code>.crx</code> files +must use appropriate HTTP headers, +so that users can install the file +by clicking a link to it. +</p> + +<p> +Google Chrome considers a file to be installable +if <b>either</b> of the following is true: +</p> + +<ul> + <li> + The file has the content type + <code>application/x-chrome-extension</code> + </li> + <li> + The file suffix is <code>.crx</code> + and <b>both</b> of the following are true: + <ul> + <li> + The file <b>is not</b> served with + the HTTP header <code>X-Content-Type-Options: nosniff</code> + </li> + <li> + The file <b>is</b> served + with one of the following content types: + <ul> + <li> empty string </li> + <li> "text/plain" </li> + <li> "application/octet-stream" </li> + <li> "unknown/unknown" </li> + <li> "application/unknown" </li> + <li> "*/*" </li> + </ul> + </li> + </ul> + </li> +</ul> + +<p> +The most common reason for failing to recognize an installable file +is that the server sends the header +<code>X-Content-Type-Options: no sniff</code>. +The second most common reason +is that the server sends an unknown content type—one +that isn't in the previous list. +To fix an HTTP header issue, +either change the configuration of the server +or try hosting the <code>.crx</code> file at another server. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/i18n-messages.html b/chrome/common/extensions/docs/templates/articles/i18n-messages.html new file mode 100644 index 0000000..f9a6620 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/i18n-messages.html @@ -0,0 +1,330 @@ +<h1>Formats: Locale-Specific Messages</h1> + + +<p> +Each internationalized extension has at least one +file named <code>messages.json</code> +that provides locale-specific strings for the extension. +This page describes the format of <code>messages.json</code> files. +For information on how to internationalize and localize your extension, +see the <a href="i18n.html">Internationalization</a> page. +</p> + +<h2 id="overview"> Field summary </h2> + +<p> +The following code shows the supported fields for +<code>messages.json</code>. +Only the "<em>name</em>" and "message" fields are required. +</p> + +<pre> +{ + "<a href="#name"><em>name</em></a>": { + "<a href="#message">message</a>": "<em>Message text, with optional placeholders.</em>", + "<a href="#description">description</a>": "<em>Translator-aimed description of the message.</em>", + "<a href="#placeholders">placeholders</a>": { + "<em>placeholder_name</em>": { + "content": "<em>A string to be placed within the message.</em>", + "example": "<em>Translator-aimed example of the placeholder string.</em>" + }, + ... + } + }, + ... +} +</pre> + +<h2 id="example"> Example </h2> + +<p> +Here's a <code>messages.json</code> file +that defines three messages +named "prompt_for_name", "hello", and "bye": +</p> + +<pre> +{ + "prompt_for_name": { + "message": "What's your name?", + "description": "Ask for the user's name" + }, + "hello": { + "message": "Hello, $USER$", + "description": "Greet the user", + "placeholders": { + "user": { + "content": "$1", + "example": "Cira" + } + } + }, + "bye": { + "message": "Goodbye, $USER$. Come back to $OUR_SITE$ soon!", + "description": "Say goodbye to the user", + "placeholders": { + "our_site": { + "content": "Example.com", + }, + "user": { + "content": "$1", + "example": "Cira" + } + } + } +} +</pre> + + +<h2>Field details</h2> + +<p> +This section describes each field +that can appear in a <code>messages.json</code> file. +For details on how the messages file is used — +for example, what happens when a locale doesn't define +all the messages — +see <a href="i18n.html">Internationalization</a>. +</p> + + +<h3 id="name">name</h3> + +<p> +Actually, there's no field called "name". +This field's name is the name of the message — +the same <em>name</em> that you see in +<code>__MSG_<em>name</em>__</code> +or <code>getMessage("<em>name</em>")</code>. +</p> + +<p> +The name is a case-insensitive key +that lets you retrieve the localized message text. +The name can include the following characters: +</p> + +<ul> + <li> A-Z </li> + <li> a-z </li> + <li> 0-9 </li> + <li> _ (underscore) </li> + <li> @ </li> +</ul> + +<p class="note"> +<b>Note:</b> +Don't define names that begin with "@@". +Those names are reserved for +<a href="i18n.html#overview-predefined">predefined messages</a>. +</p> + +<p> +Here are three examples of names, +taken from the <a href="#example">Example</a> section: +</p> + +<pre> +"prompt_for_name": { + ... +}, +"hello": { + ... +}, +"bye": { + ... +} +</pre> + +<p> +For more examples of using names, see the +<a href="i18n.html">Internationalization</a> page. +</p> + + +<h3 id="message">message</h3> + +<p> +The translated message, +in the form of a string that can contain +<a href="#placeholders">placeholders</a>. +Use <code>$<em>placeholder_name</em>$</code> +(case insensitive) +to refer to a particular placeholder. +For example, you can refer to a placeholder named "our_site" as +<code>$our_site$</code>, <code>$OUR_SITE$</code>, or <code>$oUR_sITe$</code>. +</p> + +<p> +Here are three examples of messages, +taken from the <a href="#example">Example</a> section: +</p> + +<pre> +"message": "What's your name?" +... +"message": "Hello, $USER$" +... +"message": "Goodbye, $USER$. Come back to $OUR_SITE$ soon!" +</pre> + +<p> +To put a dollar sign (<code>$</code>) into the string, +use <code>$$</code>. +For example, use the following code to specify the message +<b>Amount (in $)</b>: + +<pre> +"message": "Amount (in $$)" +</pre> + +<p> +Although placeholders such as <code>$USER$</code> are +the preferred way of referring to <em>substitution strings</em> +(strings specified using the <em>substitutions</em> parameter of +<a href="i18n.html#method-getMessage"><code>getMessage()</code></a>) +you can also refer to substitution strings directly +within the message. +For example, the following message +refers to the first three substitution strings passed into +<code>getMessage()</code>: +</p> + +<pre> +"message": "Params: $1, $2, $3" +</pre> + +<p> +Despite that example, +we recommend that you stick to using placeholders +instead of <code>$<em>n</em></code> strings +within your messages. +Think of placeholders as good variable names. +A week after you write your code, +you'll probably forget what <code>$1</code> refers to, +but you'll know what your placeholders refer to. +For more information on placeholders and substitution strings, see +the <a href="#placeholders">placeholders</a> section. +</p> + +<h3 id="description">description</h3> + +<p> +<em>Optional.</em> +A description of the message, +intended to give context +or details to help the translator +make the best possible translation. +</p> + +<p> +Here are three examples of descriptions, +taken from the <a href="#example">Example</a> section: +</p> + +<pre> +"description": "Ask for the user's name" +... +"description": "Greet the user" +... +"description": "Say goodbye to the user" +</pre> + +<h3 id="placeholders">placeholders</h3> + +<p> +<em>Optional.</em> +Defines one or more substrings +to be used within the message. +Here are two reasons you might want to use a placeholder: +</p> + +<ul> + <li> + To define the text + for a part of your message + that shouldn't be translated. + Examples: HTML code, trademarked names, formatting specifiers. + </li> + <li> + To refer to a substitution string passed into + <code>getMessage()</code>. + Example: <code>$1</code>. + </li> +</ul> + +<p> +Each placeholder has a name, +a "content" item, +and an optional "example" item. +A placeholder's name is case-insensitive +and can contain the same characters +as a <a href="#name">message name</a>. +</p> + +<p> +The "content" item's value is a string +that can refer to substitution strings, which are +specified using the +<a href="i18n.html#method-getMessage"><code>getMessage()</code></a> method's +<em>substitutions</em> parameter. +The value of a "content" item is typically something like +"Example.com" or "$1". +If you refer to +a substitution string that doesn't exist, +you get an empty string. +The following table shows how +<code>$<em>n</em></code> strings correspond to +strings specified by the <em>substitutions</em> parameter. +</p> + +<table> +<tr> +<th> <em>substitutions</em> parameter </th> +<th> Value of $1</th> +<th> Value of $2</th> +<th> Value of $3</th> +</tr> +<tr> + <td> <code>userName</code> </td> + <td> value of <code>userName</code> </td> + <td> <code>""</code> </td> + <td> <code>""</code> </td> +</tr> +<tr> + <td> <code>["Cira", "Kathy"]</code> </td> + <td> <code>"Cira"</code> </td> + <td> <code>"Kathy"</code> </td> + <td> <code>""</code> </td> +</tr> +</table> + +<p> +The "example" item +(optional, but highly recommended) +helps translators by showing how the content appears to the end user. +For example, a placeholder +for a dollar amount +should have an example like <code>"$23.45"</code>. +</p> + +<p> +The following snippet, +taken from the <a href="#example">Example</a> section, +shows a "placeholders" item that contains two placeholders +named "our_site" and "user". +The "our_site" placeholder has no "example" item +because its value is obvious from the "content" field. +</p> + +<pre> +"placeholders": { + "our_site": { + "content": "Example.com", + }, + "user": { + "content": "$1", + "example": "Cira" + } +} +</pre>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/manifest.html b/chrome/common/extensions/docs/templates/articles/manifest.html new file mode 100644 index 0000000..84b9118 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/manifest.html @@ -0,0 +1,914 @@ +<h1>Formats: Manifest Files</h1> + + +<p> +Every extension, installable web app, and theme has a +<a href="http://www.json.org">JSON</a>-formatted manifest file, +named <code>manifest.json</code>, +that provides important information. +</p> + +<h2 id="overview"> Field summary </h2> + +<p> +The following code shows the supported manifest fields, +with links to the page that discusses each field. +The only fields that are always required +are <b>name</b> and <b>version</b>. +</p> + +<pre> +{ + <em>// Required</em> + "<a href="#name">name</a>": "<em>My Extension</em>", + "<a href="#version">version</a>": "<em>versionString</em>", + "<a href="#manifest_version">manifest_version</a>": 2, + + <em>// Recommended</em> + "<a href="#description">description</a>": "<em>A plain text description</em>", + "<a href="#icons">icons</a>": { ... }, + "<a href="#default_locale">default_locale</a>": "<em>en</em>", + + <em>// Pick one (or none)</em> + "<a href="browserAction.html">browser_action</a>": {...}, + "<a href="pageAction.html">page_action</a>": {...}, + "<a href="themes.html">theme</a>": {...}, + "<a href="#app">app</a>": {...}, + + <em>// Add any of these that you need</em> + "<a href="event_pages.html">background</a>": {"persistent": false, ...}, + "<a href="background_pages.html">background</a>": {"persistent": true, ...}, + "<a href="override.html">chrome_url_overrides</a>": {...}, + "<a href="content_scripts.html">content_scripts</a>": [...], + "<a href="../extensions/contentSecurityPolicy.html">content_security_policy</a>": "<em>policyString</em>", + "<a href="fileBrowserHandler.html">file_browser_handlers</a>": [...], + "<a href="#homepage_url">homepage_url</a>": "http://<em>path/to/homepage</em>", + "<a href="#incognito">incognito</a>": "spanning" <em>or</em> "split", + "<a href="#intents">intents</a>": {...} + "<a href="#key">key</a>": "<em>publicKey</em>", + "<a href="#minimum_chrome_version">minimum_chrome_version</a>": "<em>versionString</em>", + + "<a href="#nacl_modules">nacl_modules</a>": [...], + "<a href="#offline_enabled">offline_enabled</a>": true, + "<a href="omnibox.html">omnibox</a>": { "keyword": "<em>aString</em>" }, + "<a href="options.html">options_page</a>": "<em>aFile</em>.html", + "<a href="#permissions">permissions</a>": [...], + "<a href="npapi.html">plugins</a>": [...], + "<a href="#requirements">requirements</a>": {...}, + "<a href="autoupdate.html">update_url</a>": "http://<em>path/to/updateInfo</em>.xml", + "<a href="#web_accessible_resources">web_accessible_resources</a>": [...], + "<a href="#sandbox">sandbox</a>": [...] +} +</pre> + + +<h2>Field details</h2> + +<p> +This section covers fields that aren't described in another page. +For a complete list of fields, +with links to where they're described in detail, +see the <a href="#overview">Field summary</a>. +</p> + + +<h3 id="app">app</h3> + +<p> +Used by <a href="http://developer.chrome.com/trunk/apps/app_lifecycle.html#eventpage">packaged apps</a> +to specify the app's background scripts. +Also used by <a href="https://developers.google.com/chrome/apps/docs/developers_guide#live">hosted apps</a> +to specify the URLs that the app uses. +</p> + +<h3 id="default_locale">default_locale</h3> + +<p> +Specifies the subdirectory of <code>_locales</code> +that contains the default strings for this extension. +This field is <b>required</b> in extensions +that have a <code>_locales</code> directory; +it <b>must be absent</b> in extensions +that have no <code>_locales</code> directory. +For details, see +<a href="i18n.html">Internationalization</a>. +</p> + +<h3 id="description">description</h3> + +<p> +A plain text string +(no HTML or other formatting; +no more than 132 characters) +that describes the extension. +The description should be suitable for both +the browser's extension management UI +and the <a href="https://chrome.google.com/webstore">Chrome Web Store</a>. +You can specify locale-specific strings for this field; +see <a href="i18n.html">Internationalization</a> for details. +</p> + +<h3 id="homepage_url">homepage_url</h3> + +<p> +The URL of the homepage for this extension. The extensions management page (chrome://extensions) +will contain a link to this URL. This field is particularly useful if you +<a href="hosting.html">host the extension on your own site</a>. If you distribute your +extension using the <a href="https://chrome.google.com/webstore">Chrome Web Store</a>, +the homepage URL defaults to the extension's own page. +</p> + +<h3 id="icons">icons</h3> + +<p> +One or more icons that represent the extension, app, or theme. +You should always provide a 128x128 icon; +it's used during installation and by the Chrome Web Store. +Extensions should also provide a 48x48 icon, +which is used in the extensions management page +(chrome://extensions). +You can also specify a 16x16 icon to be used as the favicon +for an extension's pages. +The 16x16 icon is also displayed in the experimental extension +<a href="experimental.infobars.html">infobar</a> +feature. +</p> + +<p> +Icons should generally be in PNG format, +because PNG has the best support for transparency. +They can, however, be in any format supported by WebKit, +including BMP, GIF, ICO, and JPEG. +Here's an example of specifying the icons: +</p> + +<pre> +"icons": { "16": "icon16.png", + "48": "icon48.png", + "128": "icon128.png" }, +</pre> + +<p class="note"> +<b>Important:</b> +Use only the documented icon sizes. +<br><br> +You might notice that Chrome sometimes resizes these icons down to smaller +sizes. For example, the install dialog might shrink the 128-pixel +icon down to 69 pixels. +<br><br> +However, the details of +Chrome's UI may change between versions, and these changes assume that +developers are using the documented sizes. If you use other sizes, +your icon may look bad in future versions of the browser. +</p> + +<p> +If you upload your extension, app, or theme using the +<a href="https://chrome.google.com/webstore/developer/dashboard">Chrome Developer Dashboard</a>, +you'll need to upload additional images, +including at least one screenshot of your extension. +For more information, +see the +<a href="http://code.google.com/chrome/webstore/">Chrome Web Store +developer documentation</a>. +</p> + +<h3 id="incognito">incognito</h3> + +<p> +Either "spanning" or "split", to specify how this extension will +behave if allowed to run in incognito mode. +</p> + +<p> +The default for extensions is "spanning", which means that the extension +will run in a single shared process. Any events or messages from an incognito +tab will be sent to the shared process, with an <em>incognito</em> flag +indicating where it came from. Because incognito tabs cannot use this shared +process, an extension using the "spanning" incognito mode will not be able to +load pages from its extension package into the main frame of an incognito tab. +</p> + +<p> +The default for installable web apps is "split", +which means that all app pages in +an incognito window will run in their own incognito process. If the app or extension contains a background page, that will also run in the incognito process. +This incognito process runs along side the regular process, but has a separate +memory-only cookie store. Each process sees events and messages only from its +own context (for example, the incognito process will see only incognito tab updates). +The processes are unable to communicate with each other. +</p> + +<p> +As a rule of thumb, if your extension or app needs to load a tab in an incognito browser, use +<em>split</em> incognito behavior. If your extension or app needs to be logged +into a remote server or persist settings locally, use <em>spanning</em> +incognito behavior. +</p> + +<h3 id="intents">intents</h3> + +<p> +A dictionary that specifies all intent handlers provided by this extension or app. Each key in the dictionary specifies an action verb that is handled by this extension. The following example specifies two handlers for the action verb "<a href="http://webintents.org/share">http://webintents.org/share</a>". +</p> + +<pre> +{ + "name": "test", + "version": "1", + "intents": { + "http://webintents.org/share": [ + { + "type": ["text/uri-list"], + "href": "/services/sharelink.html", + "title" : "Sample Link Sharing Intent", + "disposition" : "inline" + }, + { + "type": ["image/*"], + "href": "/services/shareimage.html", + "title" : "Sample Image Sharing Intent", + "disposition" : "window" + } + ] + } +} +</pre> + +<p> +The value of "type" is an array of mime types that is supported by this handler. The "href" indicates the URL of the page that handles the intent. For hosted apps, these URLs must be within the allowed set of URLs. For extensions, all URLs are inside the extension and considered relative to the extension root URL. +</p> + +<p> +The "title" is displayed in the intent picker UI when the user initiates the action specific to the handler. +</p> + +<p> +The "disposition" is either "inline" or "window". Intents with "window" disposition will open a new tab when invoked. Intents with "inline" disposition will be displayed inside the intent picker when invoked. +</p> + +<p> +For more information on intents, refer to the <a href="http://dvcs.w3.org/hg/web-intents/raw-file/tip/spec/Overview.html">Web Intents specification</a> and <a href="http://www.webintents.org">webintents.org</a>. +</p> + +<h4>Handling content types via intents</h4> + +<p> +Web Intents can be registered as content type viewers. To do that, the action verb must be <a href="http://webintents.org/view">"http://webintents.org/view"</a>, and the content type must be a white-listed MIME type. +</p> + +<table> + <tr> + <th>Whitelisted MIME types</th> + </tr> + <tr><td>application/rss+xml</td></tr> + <tr><td>application/atom+xml</td></tr> +</table> + +<h3 id="key">key</h3> + +<p> +This value can be used to control +the unique ID of an extension, app, or theme when +it is loaded during development. +</p> + +<p class="note"> +<b>Note:</b> You don't usually need to +use this value. Instead, write your +code so that the key value doesn't matter +by using <a href="overview.html#relative-urls">relative paths</a> +and <a href="extension.html#method-getURL">chrome.extension.getURL()</a>. +</p> + +<p> +To get a suitable key value, first +install your extension from a <code>.crx</code> file +(you may need to +<a href="https://chrome.google.com/webstore/developer/dashboard">upload your extension</a> +or <a href="packaging.html">package it manually</a>). +Then, in your +<a href="http://www.chromium.org/user-experience/user-data-directory">user +data directory</a>, look in the file +<code>Default/Extensions/<em><extensionId></em>/<em><versionString></em>/manifest.json</code>. +You will see the key value filled in there. +</p> + +<h3 id="minimum_chrome_version">minimum_chrome_version</h3> + +<p> +The version of Chrome that your extension, app, or theme requires, if any. +The format for this string is the same as for the +<a href="#version">version</a> field. + +<h3 id="name">name</h3> + +<p> +A short, plain text string +(no more than 45 characters) +that identifies the extension. +The name is used in the install dialog, +extension management UI, +and the <a href="https://chrome.google.com/webstore">store</a>. +You can specify locale-specific strings for this field; +see <a href="i18n.html">Internationalization</a> for details. +</p> + +<h3 id="nacl_modules">nacl_modules</h3> + +<p> +One or more mappings from MIME types to the Native Client module +that handles each type. +For example, the bold code in the following snippet +registers a Native Client module as the content handler +for the OpenOffice spreadsheet MIME type. +</p> + +<pre> +{ + "name": "Native Client OpenOffice Spreadsheet Viewer", + "version": "0.1", + "description": "Open OpenOffice spreadsheets, right in your browser.", + <b>"nacl_modules": [{ + "path": "OpenOfficeViewer.nmf", + "mime_type": "application/vnd.oasis.opendocument.spreadsheet" + }]</b> +} +</pre> + +<p> +The value of "path" is the location of a Native Client manifest +(a <code>.nmf</code> file) +within the extension directory. +For more information on Native Client and <code>.nmf</code> files, see the +<a href="http://code.google.com/chrome/nativeclient/docs/technical_overview.html">Native Client Technical Overview</a>. +</p> + +<p> +Each MIME type can be associated with only one <code>.nmf</code> file, +but a single <code>.nmf</code> file might handle multiple MIME types. +The following example shows an extension +with two <code>.nmf</code> files +that handle three MIME types. +</p> + +<pre> +{ + "name": "Spreadsheet Viewer", + "version": "0.1", + "description": "Open OpenOffice and Excel spreadsheets, right in your browser.", + "nacl_modules": [{ + "path": "OpenOfficeViewer.nmf", + "mime_type": "application/vnd.oasis.opendocument.spreadsheet" + }, + { + "path": "OpenOfficeViewer.nmf", + "mime_type": "application/vnd.oasis.opendocument.spreadsheet-template" + }, + { + "path": "ExcelViewer.nmf", + "mime_type": "application/excel" + }] +} +</pre> + +<p class="note"> +<strong>Note:</strong> +You can use Native Client modules in extensions +without specifying "nacl_modules". +Use "nacl_modules" only if you want the browser +to use your Native Client module +to display a particular type of content. +</p> + +<h3 id="offline_enabled">offline_enabled</h3> + +<p> +Whether the app or extension is expected to work offline. When Chrome detects +that it is offline, apps with this field set to true will be highlighted +on the New Tab page. +</p> + +<h3 id="permissions">permissions</h3> + +<p> +An array of permissions that the extension or app might use. +Each permission can be either one of a list of known strings +(such as "geolocation") +or a match pattern +that gives access to one or more hosts. +Permissions can help to limit damage +if your extension or app is attacked. +Some permissions are also displayed to users before installation, +as detailed in +<a href="permission_warnings.html">Permission Warnings</a>. +</p> + +<p> +If an extension API requires you to declare a permission in the manifest, +then its documentation tells you how to do so. +For example, +the <a href="tabs.html">Tabs</a> page +shows you how to +declare the "tabs" permission. +</p> + +<p class="note"> +<b>Note:</b> +As of Chrome 16, some permissions can be optional. +For details, see +<a href="permissions.html">Optional Permissions</a>. +</p> + +<p> +Here's an example of the permissions part of a manifest file +for an extension: +</p> + +<pre> +"permissions": [ + "tabs", + "bookmarks", + "http://www.blogger.com/", + "http://*.google.com/", + "unlimitedStorage" +], +</pre> + +<p> +The following table lists the permissions an extension +or packaged app can use. +</p> + +<p class="note"> +<strong>Note:</strong> +Hosted apps can use the +"background", "clipboardRead", "clipboardWrite", "geolocation", "notifications", +and "unlimitedStorage" permissions, but not any other permissions listed in this +table. +</p> + +<table> +<tr> + <th> Permission </th> <th> Description </th> +</tr> +<tr> + <td> <em>match pattern</em> </td> + <td> Specifies a <em>host permission</em>. + Required if the extension wants to interact + with the code running on pages. + Many extension capabilities, such as + <a href="xhr.html">cross-origin XMLHttpRequests</a>, + <a href="content_scripts.html#pi">programmatically injected + content scripts</a>, and <a href="cookies.html">the cookies API</a> + require host permissions. For details on the syntax, see + <a href="match_patterns.html">Match Patterns</a>. + </td> +</tr> +<tr id="bg"> + <td> "background" </td> + <td> <p> + Makes Chrome start up early and and shut down late, + so that apps and extensions can have a longer life. + </p> + + <p> + When any installed hosted app, packaged app, or extension + has "background" permission, Chrome runs (invisibly) + as soon as the user logs into their computer—before + the user launches Chrome. + The "background" permission also makes Chrome continue running + (even after its last window is closed) + until the user explicitly quits Chrome. + </p> + + <p class="note"> + <b>Note:</b> + Disabled apps and extensions + are treated as if they aren't installed. + </p> + + <p> + You typically use the "background" permission with a + <a href="background_pages.html">background page</a>, + <a href="event_pages.html">event page</a> + or (for hosted apps) a + <a href="http://code.google.com/chrome/apps/docs/background.html">background window</a>. + </p> + </td> +</tr> +<tr> + <td> "bookmarks" </td> + <td> Required if the extension uses the + <a href="bookmarks.html">chrome.bookmarks</a> module. </td> +</tr> +<tr> + <td> "chrome://favicon/" </td> + <td> Required if the extension uses the + "chrome://favicon/<em>url</em>" mechanism + to display the favicon of a page. + For example, to display the favicon of http://www.google.com/, + you declare the "chrome://favicon/" permission + and use HTML code like this: + <pre><img src="chrome://favicon/http://www.google.com/"></pre> + </td> +</tr> +<tr> + <td> "clipboardRead" </td> + <td> Required if the extension uses + <code>document.execCommand('paste')</code>. </td> +</tr> +<tr> + <td> "clipboardWrite" </td> + <td> Indicates the app or extension uses + <code>document.execCommand('copy')</code> or + <code>document.execCommand('cut')</code>. This permission is <b>required + for hosted apps</b>; it's recommended for extensions and packaged apps. + </td> +</tr> +<tr> + <td> "contentSettings" </td> + <td> Required if the extension uses the + <a href="contentSettings.html">chrome.contentSettings</a> module. </td> +</tr> +<tr> + <td> "contextMenus" </td> + <td> Required if the extension uses the + <a href="contextMenus.html">chrome.contextMenus</a> module. </td> +</tr> +<tr> + <td> "cookies" </td> + <td> Required if the extension uses the + <a href="cookies.html">chrome.cookies</a> module. </td> +</tr> +<tr> + <td> "experimental" </td> + <td> Required if the extension uses any + <a href="http://code.google.com/chrome/extensions/dev/experimental.html">chrome.experimental.* APIs</a>.</td> +</tr> +<tr> + <td id="fileBrowserHandler"> "fileBrowserHandler" </td> + <td> Required if the extension uses the + <a href="fileBrowserHandler.html">fileBrowserhandler</a> module. </td> +</tr> +<tr> + <td id="geolocation"> "geolocation" </td> + <td> Allows the extension to use the proposed HTML5 + <a href="http://dev.w3.org/geo/api/spec-source.html">geolocation API</a> + without prompting the user for permission. </td> +</tr> +<tr> + <td> "history" </td> + <td> Required if the extension uses the + <a href="history.html">chrome.history</a> module. </td> +</tr> +<tr> + <td> "idle" </td> + <td> Required if the extension uses the + <a href="idle.html">chrome.idle</a> module. </td> +</tr> +<tr> + <td> "management" </td> + <td> Required if the extension uses the + <a href="management.html">chrome.management</a> module. </td> +</tr> +<tr> + <td> "notifications" </td> + <td> Allows the extension to use the proposed HTML5 + <a href="http://www.chromium.org/developers/design-documents/desktop-notifications/api-specification">notification API</a> + without calling permission methods + (such as <code>checkPermission()</code>). + For more information see + <a href="notifications.html">Desktop Notifications</a>.</td> +</tr> +<tr> + <td> "privacy" </td> + <td> Required if the extension uses the + <a href="privacy.html">chrome.privacy</a> module. </td> +</tr> +<tr> + <td> "proxy" </td> + <td> Required if the extension uses the + <a href="proxy.html">chrome.proxy</a> module. </td> +</tr> +<tr> + <td> "storage" </td> + <td> Required if the extension uses the + <a href="storage.html">chrome.storage</a> module. </td> +</tr> +<tr> + <td> "tabs" </td> + <td> Required if the extension uses the + <a href="tabs.html">chrome.tabs</a> or + <a href="windows.html">chrome.windows</a> module. </td> +</tr> +<tr> + <td> "tts" </td> + <td> Required if the extension uses the + <a href="tts.html">chrome.tts</a> module. </td> +</tr> +<tr> + <td> "ttsEngine" </td> + <td> Required if the extension uses the + <a href="ttsEngine.html">chrome.ttsEngine</a> module. </td> +</tr> +<tr> + <td> "unlimitedStorage"</td> + <td> Provides an unlimited quota for storing HTML5 client-side data, + such as databases and local storage files. + Without this permission, the extension is limited to + 5 MB of local storage. + + <p class="note"> + <b>Note:</b> + This permission applies only to Web SQL Database and application cache + (see issue <a href="http://crbug.com/58985">58985</a>). + Also, it doesn't currently work with wildcard subdomains such as + <code>http://*.example.com</code>. + </p> + </td> +<tr> +<tr> + <td> "webNavigation" </td> + <td> Required if the extension uses the + <a href="webNavigation.html">chrome.webNavigation</a> module. </td> +</tr> +<tr> + <td> "webRequest" </td> + <td> Required if the extension uses the + <a href="webRequest.html">chrome.webRequest</a> module. </td> +</tr> +<tr> + <td> "webRequestBlocking" </td> + <td> Required if the extension uses the + <a href="webRequest.html">chrome.webRequest</a> module in a blocking + fashion. </td> +</tr> +</tr> +</table> + +<h3 id="requirements">requirements</h3> + +<p> +Technologies required by the app or extension. +Hosting sites such as the Chrome Web Store may use this list +to dissuade users from installing apps or extensions +that will not work on their computer. +Supported requirements currently include "3D" and "plugins"; +additional requirements checks may be added in the future. +</p> + +<p> +The "3D" requirement denotes GPU hardware acceleration. +The "webgl" requirement refers to the +<a href="http://www.khronos.org/webgl/">WebGL API</a>. +For more information on Chrome 3D graphics support, +see the help article on +<a href="http://www.google.com/support/chrome/bin/answer.py?answer=1220892">WebGL and 3D graphics</a>. +You can list the 3D-related features your app requires, +as demonstrated in the following example: +</p> + +<pre> +"requirements": { + "3D": { + "features": ["webgl"] + } +} +</pre> + +<p> +The "plugins" requirement indicates +if an app or extension requires NPAPI to run. +This requirement is enabled by default +when the manifest includes the +<a href="http://developer.chrome.com/extensions/npapi.html">"plugins" field</a>. +For apps and extensions that still work when plugins aren't available, +you can disable this requirement +by setting NPAPI to false. +You can also enable this requirement manually, +by setting NPAPI to true, +as shown in this example: +</p> + +<pre> +"requirements": { + "plugins": { + "npapi": true + } +} +</pre> + + +<h3 id="version">version</h3> + +<p> +One to four dot-separated integers +identifying the version of this extension. +A couple of rules apply to the integers: +they must be between 0 and 65535, inclusive, +and non-zero integers can't start with 0. +For example, 99999 and 032 are both invalid. +</p> + +<p> +Here are some examples of valid versions: +</p> + +<ul> + <li> <code>"version": "1"</code> </li> + <li> <code>"version": "1.0"</code> </li> + <li> <code>"version": "2.10.2"</code> </li> + <li> <code>"version": "3.1.2.4567"</code> </li> +</ul> + +<p> +The autoupdate system compares versions +to determine whether an installed extension +needs to be updated. +If the published extension has a newer version string +than the installed extension, +then the extension is automatically updated. +</p> + +<p> +The comparison starts with the leftmost integers. +If those integers are equal, +the integers to the right are compared, +and so on. +For example, 1.2.0 is a newer version than 1.1.9.9999. +</p> + +<p> +A missing integer is equal to zero. +For example, 1.1.9.9999 is newer than 1.1. +</p> + +<p> +For more information, see +<a href="autoupdate.html">Autoupdating</a>. +</p> + + + +<h3 id="manifest_version">manifest_version</h3> + +<p> +One integer specifying the version of the manifest file format your package +requires. As of Chrome 18, developers <em>should</em> specify <code>2</code> +(without quotes) to use the format as described by this document: +</p> + +<pre>"manifest_version": 2</pre> + +<p> +Consider manifest version 1 <em>deprecated</em> as of Chrome 18. Version 2 is +not yet <em>required</em>, but we will, at some point in the not-too-distant +future, stop supporting packages using deprecated manifest versions. Extensions, +applications, and themes that aren't ready to make the jump to the new manifest +version in Chrome 18 can either explicitly specify version <code>1</code>, or +leave the key off entirely. +</p> + +<p> +The changes between version 1 and version 2 of the manifest file format are +described in detail in <a href="manifestVersion.html">the +<code>manifest_version</code> documentation.</a> +</p> + +<p class="caution"> + Setting <code>manifest_version</code> 2 in Chrome 17 or lower is not + recommended. If your extension needs to work in older versions of Chrome, + stick with version 1 for the moment. We'll give you ample warning before + version 1 stops working. +</p> + +<h3 id="web_accessible_resources">web_accessible_resources</h3> + +<p> +An array of strings specifying the paths (relative to the package root) of +packaged resources that are expected to be usable in the context of a web page. +For example, an extension that injects a content script with the intention of +building up some custom interface for <code>example.com</code> would whitelist +any resources that interface requires (images, icons, stylesheets, scripts, +etc.) as follows: +</p> + +<pre>{ + ... + "web_accessible_resources": [ + "images/my-awesome-image1.png", + "images/my-amazing-icon1.png", + "style/double-rainbow.css", + "script/double-rainbow.js" + ], + ... +}</pre> + +<p> +These resources would then be available in a webpage via the URL +<code>chrome-extension://[PACKAGE ID]/[PATH]</code>, which can be generated with +the <a href="extension.html#method-getURL"> + <code>chrome.extension.getURL</code> +</a> method. Whitelisted resources are served with appropriate +<a href="http://www.w3.org/TR/cors/">CORS</a> headers, so they're available via +mechanisms like XHR. +</p> + +<p> +Injected content scripts themselves do not need to be whitelisted. +</p> + +<p> +Prior to manifest version 2 all resources within an extension could be accessed +from any page on the web. This allowed a malicious website to +<a href="http://en.wikipedia.org/wiki/Device_fingerprint">fingerprint</a> the +extensions that a user has installed or exploit vulnerabilities (for example +<a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS bugs</a>)within +installed extensions. Limiting availability to only resources which are +explicitly intended to be web accessible serves to both minimize the available +attack surface and protect the privacy of users. +</p> + +<h4>Default Availability</h4> + +<p> +Resources inside of packages using <a href="#manifest_version"><code>manifest_version</code></a> +2 or above are <strong>blocked by default</strong>, and must be whitelisted +for use via this property. +</p> + +<p> +Resources inside of packages using <code>manifest_version</code> 1 are available +by default, but <em>if</em> you do set this property, then it will be treated as +a complete list of all whitelisted resources. Resources not listed will be +blocked. +</p> + +<h3 id="sandbox">sandbox</h3> + +<p> +Defines an collection of app or extension pages that are to be served +in a sandboxed unique origin, and optionally a Content Security Policy to use +with them. Being in a sandbox has two implications: +</p> + +<ol> +<li>A sandboxed page will not have access to extension or app APIs, or +direct access to non-sandboxed pages (it may communicate with them via +<code>postMessage()</code>).</li> +<li> + <p>A sandboxed page is not subject to the + <a href="../extensions/contentSecurityPolicy.html">Content Security Policy + (CSP)</a> used by the rest of the app or extension (it has its own separate + CSP value). This means that, for example, it can use inline script and + <code>eval</code>.</p> + + <p>For example, here's how to specify that two extension pages are to be + served in a sandbox with a custom CSP:</p> + + <pre>{ + ... + "sandbox": { + "pages": [ + "page1.html", + "directory/page2.html" + ] + <i>// content_security_policy is optional.</i> + "content_security_policy": + "sandbox allow-scripts; script-src https://www.google.com" + ], + ... +}</pre> + + <p> + If not specified, the default <code>content_security_policy</code> value is + <code>sandbox allow-scripts allow-forms</code>. You can specify your CSP + value to restrict the sandbox even further, but it must have the <code>sandbox</code> + directive and may not have the <code>allow-same-origin</code> token (see + <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-iframe-element.html#attr-iframe-sandbox">the + HTML5 specification</a> for possible sandbox tokens). + </p> +</li> +</ol> + +<p> +Note that you only need to list pages that you expected to be loaded in +windows or frames. Resources used by sandboxed pages (e.g. stylesheets or +JavaScript source files) do not need to appear in the +<code>sandboxed_page</code> list, they will use the sandbox of the page +that embeds them. +</p> + +<p> +<a href="sandboxingEval.html">"Using eval in Chrome Extensions. Safely."</a> +goes into more detail about implementing a sandboxing workflow that enables use +of libraries that would otherwise have issues executing under extension's +<a href="../extensions/contentSecurityPolicy.html">default Content Security +Policy</a>. +</p> + +<p> +Sandboxed page may only be specified when using +<a href="#manifest_version"><code>manifest_version</code></a> 2 or above. +</p> diff --git a/chrome/common/extensions/docs/templates/articles/manifestVersion.html b/chrome/common/extensions/docs/templates/articles/manifestVersion.html new file mode 100644 index 0000000..a39ebb3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/manifestVersion.html @@ -0,0 +1,241 @@ +<h1>Manifest Version</h1> + +<style type="text/css"> +#schedule h3 { + margin-bottom:0; +} + +#schedule p { + margin-top:0; + margin-bottom:1em; +} +</style> + +<p> + Extensions, themes, and applications are simply bundles of resources, wrapped + up with a <a href="manifest.html"><code>manifest.json</code></a> file that + describes the package's contents. The format of this file is generally stable, + but occasionally breaking changes must be made to address important issues. + Developers should specify which version of the manifest specification their + package targets by setting a <code>manifest_version</code> key in their + manifests. +</p> + +<h2 id="current-version">Current Version</h2> + +<p> + Developers should currently specify + <strong><code>'manifest_version': 2</code></strong>: +</p> + +<pre>{ + ..., + "manifest_version": 2, + ... +}</pre> + +<p> + Manifest version 1 was <em>deprecated</em> in Chrome 18, and support will + be phased out according to the following schedule. +</p> + +<h2 id="manifest-v1-support-schedule">Manifest version 1 support schedule</h2> + +<div id="schedule"> +<h3 id="manifest-v1-m21">Chrome 21</h3> +<p><em>Beta: Early July 2012; + Stable: Mid-August 2012</em></p> +<ul> + <li>The Web Store will block creation of new manifest version 1 items. + <li>The Web Store will allow updates to existing manifest version 1 items. +</ul> + +<h3 id="manifest-v1-m23">Chrome 23</h3> +<p><em>Beta: Late September 2012; + Stable: Early November 2012</em></p> +<ul> + <li>The Web Store will block updates to manifest version 1 items. + <li>Chrome will stop packaging manifest version 1 items (or loading + them for development). +</ul> + +<h3 id="manifest-v1-2012q1">First Quarter 2013</h3> +<ul> + <li>The Web Store will remove manifest version 1 items from the wall, + search results, and category pages. + <li>Notice emails will be sent to all developers with manifest + version 1 items still in the store reminding them that these + items will be unpublished and providing update instructions. +</ul> + +<h3 id="manifest-v1-2012q2">Second Quarter 2013</h3> +<ul> + <li>The Web Store will unpublish all manifest version 1 items. + <li>Final notice emails will be sent to developers with manifest + version 1 items still in the Web Store. + <li>Chrome will continue to load and run installed manifest + version 1 items. +</ul> + +<h3 id="manifest-v1-2012q3">Third Quarter 2013</h3> +<ul> + <li>Chrome will stop loading or running manifest + version 1 items. +</ul> +</div> + +<h2 id="manifest-v1-changes">Changes between version 1 and 2</h2> + +<ul> + <li> + <p> + A content security policy is set to <code>`script-src 'self' + chrome-extension-resource:; object-src 'self'</code> by default. This has + a variety of impacts on developers, described at length in the + <a href="contentSecurityPolicy.html"> + <code>content_security_policy</code></a> documentation. + </p> + </li> + <li> + <p> + A package's resources are no longer available by default to external + websites (as the <code>src</code> of an image, or a <code>script</code> + tag). If you want a website to be able to load a resource contained in + your package, you'll need to explicitly whitelist it via the + <a href="manifest.html#web_accessible_resources"> + <code>web_accessible_resources</code> + </a> manifest attribute. This is particularly relevant for extensions that + build up an interface on a website via injected content scripts. + </p> + </li> + <li> + <p> + The <code>background_page</code> property has been replaced with a + <code>background</code> property that contains <em>either</em> a + <code>scripts</code> or <code>page</code> property. Details are available + in the <a href="event_pages.html">Event Pages</a> documentation. + </p> + </li> + <li> + <p>Browser action changes:</p> + <ul> + <li> + <p> + The <code>browser_actions</code> key in the manifest, and the + <code>chrome.browserActions</code> API are gone. Use the singular + <a href="browserAction.html"> + <code>browser_action</code> and <code>chrome.browserAction</code> + </a> instead. + </p> + </li> + <li> + <p> + The <code>icons</code> property of <code>browser_action</code> has + been removed. Use <a href="browserAction.html#manifest"> + the <code>default_icon</code> property + </a> or <a href="browserAction.html#method-setIcon"> + <code>chrome.browserAction.setIcon</code> + </a> instead. + </p> + </li> + <li> + <p> + The <code>name</code> property of <code>browser_action</code> has been + removed. Use <a href="browserAction.html#manifest"> + the <code>default_title</code> property + </a> or <a href="browserAction.html#method-setTitle"> + <code>chrome.browserAction.setTitle</code> + </a> instead. + </p> + </li> + <li> + <p> + The <code>popup</code> property of <code>browser_action</code> has + been removed. Use <a href="browserAction.html#manifest"> + the <code>default_popup</code> property + </a> or <a href="browserAction.html#method-setPopup"> + <code>chrome.browserAction.setPopup</code> + </a> instead. + </p> + </li> + <li> + <p> + The <code>default_popup</code> property of <code>browser_action</code> + can no longer be specified as an object. It must be a string. + </p> + </li> + </ul> + </li> + <li> + <p>Page action changes:</p> + <ul> + <li> + <p> + The <code>page_actions</code> key in the manifest, and the + <code>chrome.pageActions</code> API are gone. Use the singular + <a href="pageAction.html"> + <code>page_action</code> and <code>chrome.pageAction</code> + </a> instead. + </p> + </li> + <li> + <p> + The <code>icons</code> property of <code>page_action</code> has been + removed. Use <a href="pageAction.html#manifest"> + the <code>default_icon</code> property + </a> or <a href="pageAction.html#method-setIcon"> + <code>chrome.pageAction.setIcon</code> + </a> instead. + </p> + </li> + <li> + <p> + The <code>name</code> property of <code>page_action</code> has been + removed. Use <a href="pageAction.html#manifest"> + the <code>default_title</code> property + </a> or <a href="pageAction.html#method-setTitle"> + <code>chrome.pageAction.setTitle</code> + </a> instead. + </p> + </li> + <li> + <p> + The <code>popup</code> property of <code>page_action</code> has been + removed. Use <a href="pageAction.html#manifest"> + the <code>default_popup</code> property + </a> or <a href="pageAction.html#method-setPopup"> + <code>chrome.pageAction.setPopup</code> + </a> instead. + </p> + </li> + <li> + <p> + The <code>default_popup</code> property of <code>page_action</code> + can no longer be specified as an object. It must be a string. + </p> + </li> + <li> + <p> + The <code>chrome.self</code> API has been removed. Use + <a href="extension.html"><code>chrome.extension</code></a> instead. + </p> + </li> + </ul> + </li> + <li> + <p> + <code>chrome.extension.getTabContentses</code> (!!!) and + <code>chrome.extension.getExtensionTabs</code> are gone. Use + <a href="extension.html#method-getViews"> + <code>chrome.extension.getViews({ "type": "tab" })</code> + </a> instead. + </p> + </li> + <li> + <p> + <code>Port.tab</code> is gone. Use + <a href="extension.html#type-Port"><code>Port.sender</code></a> + instead. + </p> + </li> +</ul> diff --git a/chrome/common/extensions/docs/templates/articles/match_patterns.html b/chrome/common/extensions/docs/templates/articles/match_patterns.html new file mode 100644 index 0000000..d0b5cb0 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/match_patterns.html @@ -0,0 +1,261 @@ +<h1>Match Patterns</h1> + +<p> +<a href="content_scripts.html">Content scripts</a> operate on +a set of URLs defined by match patterns. +You can put one or more match patterns +in the <code>"matches"</code> part of +a content script's section of the manifest, +as well as in the <code>"exclude_matches"</code> section. +This page describes the match pattern syntax — +the rules you need to follow when you specify +which URLs your content script affects. +</p> + +<p> +A match pattern is essentially a URL +that begins with a permitted scheme (<code>http</code>, +<code>https</code>, <code>file</code>, <code>ftp</code>, or +<code>chrome-extension</code>), +and that can contain '<code>*</code>' characters. +The special pattern +<code><all_urls></code> matches any URL +that starts with a permitted scheme. +Each match pattern has 3 parts:</p> +</p> + +<ul> + <li> <em>scheme</em> — + for example, <code>http</code> or <code>file</code> + or <code>*</code> + <p class="note"> + <b>Note:</b> + Access to <code>file</code> URLs isn't automatic. + The user must visit the extensions management page + and opt in to <code>file</code> access for each extension that requests it. + </p> + </li> + <li> <em>host</em> — + for example, <code>www.google.com</code> + or <code>*.google.com</code> + or <code>*</code>; + if the scheme is <code>file</code>, + there is no <em>host</em> part + </li> + <li> <em>path</em> — + for example, <code>/*</code>, <code>/foo* </code>, + or <code>/foo/bar </code> + </li> +</ul> + +<p>Here's the basic syntax:</p> + +<pre> +<em><url-pattern></em> := <em><scheme></em>://<em><host></em><em><path></em> +<em><scheme></em> := '*' | 'http' | 'https' | 'file' | 'ftp' | 'chrome-extension' +<em><host></em> := '*' | '*.' <em><any char except '/' and '*'></em>+ +<em><path></em> := '/' <em><any chars></em> +</pre> + +<p> +The meaning of '<code>*</code>' depends on whether +it's in the <em>scheme</em>, <em>host</em>, or <em>path</em> part. +If the <em>scheme</em> is <code>*</code>, +then it matches either <code>http</code> or <code>https</code>. +If the <em>host</em> is just <code>*</code>, +then it matches any host. +If the <em>host</em> is <code>*.<em>hostname</em></code>, +then it matches the specified host or any of its subdomains. +In the <em>path</em> section, +each '<code>*</code>' matches 0 or more characters. +The following table shows some valid patterns. +</p> + +<table class="columns"> +<tbody> +<tr> + <th style="margin-left:0; padding-left:0">Pattern</th> + <th style="margin-left:0; padding-left:0">What it does</th> + <th style="margin-left:0; padding-left:0">Examples of matching URLs</th> +</tr> + +<tr> + <td> + <code>http://*/*</code> + </td> + + <td>Matches any URL that uses the <code>http</code> scheme</td> + + <td> + http://www.google.com/<br> + http://example.org/foo/bar.html + </td> +</tr> + +<tr> + <td> + <code>http://*/foo*</code> + </td> + + <td> + Matches any URL that uses the <code>http</code> scheme, on any host, + as long as the path starts with <code>/foo</code> + </td> + + <td> + http://example.com/foo/bar.html<br> + http://www.google.com/foo<b></b> + </td> +</tr> + +<tr> + <td> + <code>https://*.google.com/foo*bar </code> + </td> + + <td> + Matches any URL that uses the <code>https</code> scheme, + is on a google.com host + (such as www.google.com, docs.google.com, or google.com), + as long as the path starts with <code>/foo</code> + and ends with <code>bar</code> + </td> + + <td> + http://www.google.com/foo/baz/bar<br> + http://docs.google.com/foobar + </td> +</tr> + +<tr> + <td> + <code>http://example.org/foo/bar.html </code> + </td> + + <td>Matches the specified URL</td> + + <td> + http://example.org/foo/bar.html + </td> +</tr> + +<tr> + <td> + <code>file:///foo*</code> + </td> + + <td>Matches any local file whose path starts with <code>/foo</code> + </td> + + <td> + file:///foo/bar.html<br> + file:///foo + </td> +</tr> + +<tr> + <td> + <code>http://127.0.0.1/*</code> + </td> + + <td> + Matches any URL that uses the <code>http</code> scheme + and is on the host 127.0.0.1 + </td> + <td> + http://127.0.0.1/<br> + http://127.0.0.1/foo/bar.html + </td> +</tr> + +<tr> + <td> + <code>*://mail.google.com/* </code> + </td> + + <td> + Matches any URL that starts with + <code>http://mail.google.com</code> or + <code>https://mail.google.com</code>. + </td> + + <td> + http://mail.google.com/foo/baz/bar<br> + https://mail.google.com/foobar + </td> +</tr> + +<tr> + <td> + <code>chrome-extension://*/* </code> + </td> + + <td> + Matches any URL pointing to an extension (the first <code>*</code> + represents a filter for extension IDs, the second for paths). + </td> + + <td> + chrome-extension://askla...asdf/options.html + </td> +</tr> + +<tr> + <td> + <code><all_urls></code> + </td> + + <td> + Matches any URL that uses a permitted scheme. + (See the beginning of this section for the list of permitted + schemes.) + </td> + <td> + http://example.org/foo/bar.html<br> + file:///bar/baz.html + </td> +</tr> +</tbody> +</table> + +<p> +Here are some examples of <em>invalid</em> pattern matches: +</p> + +<table class="columns"> +<tbody> +<tr> + <th style="margin-left:0; padding-left:0">Bad pattern</th> + <th style="margin-left:0; padding-left:0">Why it's bad</th> +</tr> + +<tr> + <td><code>http://www.google.com</code></td> + <td>No <em>path</em></td> +</tr> + +<tr> + <td><code>http://*foo/bar</code></td> + <td>'*' in the <em>host</em> can be followed only by a '.' or '/'</td> +</tr> + +<tr> + <td><code>http://foo.*.bar/baz </code></td> + <td>If '*' is in the <em>host</em>, it must be the first character</td> + </tr> + +<tr> + <td><code>http:/bar</code></td> + <td>Missing <em>scheme</em> separator ("/" should be "//")</td> +</tr> + +<tr> + <td><code>foo://*</code></td> + <td>Invalid <em>scheme</em></td> +</tr> +</tbody> +</table> + +<p> +Some schemes are not supported in all contexts. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/messaging.html b/chrome/common/extensions/docs/templates/articles/messaging.html new file mode 100644 index 0000000..fa1f32d --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/messaging.html @@ -0,0 +1,275 @@ +<h1>Message Passing</h1> + + +<p> +Since content scripts run in the context of a web page and not the extension, +they often need some way of communicating with the rest of the extension. For +example, an RSS reader extension might use content scripts to detect the +presence of an RSS feed on a page, then notify the background page in order to +display a page action icon for that page. + +<p> +Communication between extensions and their content scripts works by using +message passing. Either side can listen for messages sent from the other end, +and respond on the same channel. A message can contain any valid JSON object +(null, boolean, number, string, array, or object). There is a simple API for +<a href="#simple">one-time requests</a> +and a more complex API that allows you to have +<a href="#connect">long-lived connections</a> +for exchanging multiple messages with a shared context. It is also possible to +send a message to another extension if you know its ID, which is covered in +the +<a href="#external">cross-extension messages</a> +section. + + +<h2 id="simple">Simple one-time requests</h2> +<p> +If you only need to send a single message to another part of your extension +(and optionally get a response back), you should use the simplified +<a href="extension.html#method-sendMessage">chrome.extension.sendMessage()</a> +or +<a href="tabs.html#method-sendMessage">chrome.tabs.sendMessage()</a> +methods. This lets you send a one-time JSON-serializable message from a +content script to extension, or vice versa, respectively. An optional +callback parameter allows you handle the response from the other side, if +there is one. + +<p> +Sending a request from a content script looks like this: +<pre> +contentscript.js +================ +chrome.extension.sendMessage({greeting: "hello"}, function(response) { + console.log(response.farewell); +}); +</pre> + +<p> +Sending a request from the extension to a content script looks very similar, +except that you need to specify which tab to send it to. This example +demonstrates sending a message to the content script in the selected tab. +<pre> +background.html +=============== +chrome.tabs.getSelected(null, function(tab) { + chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { + console.log(response.farewell); + }); +}); +</pre> + +<p> +On the receiving end, you need to set up an +<a href="extension.html#event-onMessage">chrome.extension.onMessage</a> +event listener to handle the message. This looks the same from a content +script or extension page. +<pre> +chrome.extension.onMessage.addListener( + function(request, sender, sendResponse) { + console.log(sender.tab ? + "from a content script:" + sender.tab.url : + "from the extension"); + if (request.greeting == "hello") + sendResponse({farewell: "goodbye"}); + }); +</pre> + +<p class="note"> +<b>Note:</b> If multiple pages are listening for onMessage events, only the +first to call sendResponse() for a particular event will succeed in sending the +response. All other responses to that event will be ignored. +</p> + + +<h2 id="connect">Long-lived connections</h2> +<p> +Sometimes it's useful to have a conversation that lasts longer than a single +request and response. In this case, you can open a long-lived channel from +your content script to an extension page, or vice versa, using +<a href="extension.html#method-connect">chrome.extension.connect()</a> +or +<a href="tabs.html#method-connect">chrome.tabs.connect()</a> respectively. The +channel can optionally have a name, allowing you to distinguish between +different types of connections. + +<p> +One use case might be an automatic form fill extension. The content script +could open a channel to the extension page for a particular login, and send a +message to the extension for each input element on the page to request the +form data to fill in. The shared connection allows the extension to keep +shared state linking the several messages coming from the content script. + +<p> +When establishing a connection, each end is given a +<a href="extension.html#type-Port">Port</a> +object which is used for sending and receiving messages through that +connection. + +<p> +Here is how you open a channel from a content script, and send and listen for +messages: +<pre> +contentscript.js +================ +var port = chrome.extension.connect({name: "knockknock"}); +port.postMessage({joke: "Knock knock"}); +port.onMessage.addListener(function(msg) { + if (msg.question == "Who's there?") + port.postMessage({answer: "Madame"}); + else if (msg.question == "Madame who?") + port.postMessage({answer: "Madame... Bovary"}); +}); +</pre> + +<p> +Sending a request from the extension to a content script looks very similar, +except that you need to specify which tab to connect to. Simply replace the +call to connect in the above example with +<a href="tabs.html#method-connect">chrome.tabs.connect(tabId, {name: +"knockknock"})</a>. + +<p> +In order to handle incoming connections, you need to set up a +<a href="extension.html#event-onConnect">chrome.extension.onConnect</a> +event listener. This looks the same from a content script or an extension +page. When another part of your extension calls "connect()", this event is +fired, along with the +<a href="extension.html#type-Port">Port</a> +object you can use to send and receive messages through the connection. Here's +what it looks like to respond to incoming connections: +<pre> +chrome.extension.onConnect.addListener(function(port) { + console.assert(port.name == "knockknock"); + port.onMessage.addListener(function(msg) { + if (msg.joke == "Knock knock") + port.postMessage({question: "Who's there?"}); + else if (msg.answer == "Madame") + port.postMessage({question: "Madame who?"}); + else if (msg.answer == "Madame... Bovary") + port.postMessage({question: "I don't get it."}); + }); +}); +</pre> + +<p> +You may want to find out when a connection is closed, for example if you are +maintaining separate state for each open port. For this you can listen to the +<a href="extension.html#type-Port">Port.onDisconnect</a> +event. This event is fired either when the other side of the channel manually +calls +<a href="extension.html#type-Port">Port.disconnect()</a>, or when the page +containing the port is unloaded (for example if the tab is navigated). +onDisconnect is guaranteed to be fired only once for any given port. + + +<h2 id="external">Cross-extension messaging</h2> +<p> +In addition to sending messages between different components in your +extension, you can use the messaging API to communicate with other extensions. +This lets you expose a public API that other extensions can take advantage of. + +<p> +Listening for incoming requests and connections is similar to the internal +case, except you use the +<a href="extension.html#event-onMessageExternal">chrome.extension.onMessageExternal</a> +or +<a href="extension.html#event-onConnectExternal">chrome.extension.onConnectExternal</a> +methods. Here's an example of each: +<pre> +// For simple requests: +chrome.extension.onMessageExternal.addListener( + function(request, sender, sendResponse) { + if (sender.id == blacklistedExtension) + return; // don't allow this extension access + else if (request.getTargetData) + sendResponse({targetData: targetData}); + else if (request.activateLasers) { + var success = activateLasers(); + sendResponse({activateLasers: success}); + } + }); + +// For long-lived connections: +chrome.extension.onConnectExternal.addListener(function(port) { + port.onMessage.addListener(function(msg) { + // See other examples for sample onMessage handlers. + }); +}); +</pre> + +<p> +Likewise, sending a message to another extension is similar to sending one +within your extension. The only difference is that you must pass the ID of the +extension you want to communicate with. For example: +<pre> +// The ID of the extension we want to talk to. +var laserExtensionId = "abcdefghijklmnoabcdefhijklmnoabc"; + +// Make a simple request: +chrome.extension.sendMessage(laserExtensionId, {getTargetData: true}, + function(response) { + if (targetInRange(response.targetData)) + chrome.extension.sendMessage(laserExtensionId, {activateLasers: true}); + }); + +// Start a long-running conversation: +var port = chrome.extension.connect(laserExtensionId); +port.postMessage(...); +</pre> + +<h2 id="security-considerations">Security considerations</h2> + +<p> +When receiving a message from a content script or another extension, your +background page should be careful not to fall victim to <a +href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site +scripting</a>. Specifically, avoid using dangerous APIs such as the +below: +</p> +<pre>background.html +=============== +chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { + // WARNING! Might be evaluating an evil script! + var resp = eval("(" + response.farewell + ")"); +}); + +background.html +=============== +chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { + // WARNING! Might be injecting a malicious script! + document.getElementById("resp").innerHTML = response.farewell; +}); +</pre> +<p> +Instead, prefer safer APIs that do not run scripts: +</p> +<pre>background.html +=============== +chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { + // JSON.parse does not evaluate the attacker's scripts. + var resp = JSON.parse(response.farewell); +}); + +background.html +=============== +chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) { + // innerText does not let the attacker inject HTML elements. + document.getElementById("resp").innerText = response.farewell; +}); +</pre> + +<h2 id="examples">Examples</h2> + +<p> +You can find simple examples of communication via messages in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/messaging/">examples/api/messaging</a> +directory. +Also see the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/howto/contentscript_xhr">contentscript_xhr</a> example, +in which a content script and its parent extension exchange messages, +so that the parent extension can perform +cross-site requests on behalf of the content script. +For more examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/notifications.html b/chrome/common/extensions/docs/templates/articles/notifications.html new file mode 100644 index 0000000..12014c6 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/notifications.html @@ -0,0 +1,116 @@ +<h1>Desktop Notifications</h1> + + + +<p> +Use desktop notifications to notify users that something +important has happened. +Notifications appear outside the browser window. +As the following snapshots show, +the details of how notifications look +and where they're shown depend on the platform. +</p> + +<img src="{{static}}/images/notification-windows.png" + width="28%" style="margin:2em 0.5em 1em; border:1px solid black;" + alt="Notifications on Microsoft Windows"/> +<img src="{{static}}/images/notification-mac.png" + width="28%" style="margin:2em 0.5em 1em; border:1px solid black;" + alt="Notifications on Mac OS X"/> +<img src="{{static}}/images/notification-linux.png" + width="28%" style="margin:2em 0.5em 1em; border:1px solid black;" + alt="Notifications on Ubuntu Linux"/> + +<p> +You create the notification window +using a bit of JavaScript and, optionally, +an HTML page packaged inside your extension. +</p> + + +<h2 id="example">Example</h2> + +<p>First, declare the <code>notifications</code> permission in your manifest:</p> +<pre> +{ + "name": "My extension", + "manifest_version": 2, + ... +<b> "permissions": [ + "notifications" + ]</b>, + ... + // <strong>Note:</strong> Because of <a href="http://code.google.com/p/chromium/issues/detail?id=134315">bug 134315</a>, you must declare any images you + // want to use with createNotification() as a web accessible resource. +<b> "web_accessible_resources": [ + "48.png" + ]</b>, +} +</pre> + +<p>Then, use <code>webkitNotifications</code> object to create notifications:</p> + +<pre> +// <strong>Note:</strong> There's no need to call webkitNotifications.checkPermission(). +// Extensions that declare the <em>notifications</em> permission are always +// allowed create notifications. + +// Create a simple text notification: +var notification = webkitNotifications.createNotification( + '48.png', // icon url - can be relative + 'Hello!', // notification title + 'Lorem ipsum...' // notification body text +); + +// Or create an HTML notification: +var notification = webkitNotifications.createHTMLNotification( + 'notification.html' // html url - can be relative +); + +// Then show the notification. +notification.show(); +</pre> + +<h2>API Reference</h2> + +<p>See the <a href="http://dev.chromium.org/developers/design-documents/desktop-notifications/api-specification">Desktop Notifications Draft Specification</a>.</p> + + +<h2 id="communication">Communicating with Other Views</h2> + +<p> +You can communicate between a notification +and other views in your extension using +<a href="extension.html#method-getBackgroundPage">getBackgroundPage()</a> and +<a href="extension.html#method-getViews">getViews()</a>. For example: +</p> + +<pre> +// Inside a notification... +chrome.extension.getBackgroundPage().doThing(); + +// From the background page... +chrome.extension.getViews({type:"notification"}).forEach(function(win) { + win.doOtherThing(); +}); +</pre> + + +<h2 id="examples">More Examples</h2> + +<p> +You can find a simple example +of using notifications in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/notifications/">examples/api/notifications</a> +directory. +For other examples +and for help in viewing the source code, +see <a href="samples.html">Samples</a>. +</p> + +<p> +Also see html5rocks.com's +<a href="http://www.html5rocks.com/tutorials/notifications/quick/">notifications tutorial</a>. +Ignore the permission-related code; +it's unnecessary if you declare the "notifications" permission. +</p> diff --git a/chrome/common/extensions/docs/templates/articles/npapi.html b/chrome/common/extensions/docs/templates/articles/npapi.html new file mode 100644 index 0000000..b3408ab --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/npapi.html @@ -0,0 +1,97 @@ +<h1>NPAPI Plugins</h1> + +<p> +Leveraging HTML and JavaScript +makes developing new extensions really easy, +but what if you have existing legacy or proprietary code +that you want to reuse in your extension? +You can bundle an NPAPI plugin with your extension, +allowing you to call into native binary code from JavaScript. +</p> + +<h2>Warning</h2> + +<p align="center"><b>NPAPI is a really big hammer that should only be used when no other approach will work.</b> + +<p>Code running in an NPAPI plugin has the full permissions of the current user and is not sandboxed or shielded from malicious input by Google Chrome in any way. You should be especially cautious when processing input from untrusted sources, such as when working with <a href="content_scripts.html#security-considerations">content scripts</a> or XMLHttpRequest. + +<p>Because of the additional security risks NPAPI poses to users, extensions that use it will require manual review before being accepted in the +<a href="https://chrome.google.com/webstore">Chrome Web Store</a>.</p> + +<h2>Details</h2> + +<p> +How to develop an NPAPI plugin is outside the scope of this document. +See <a href="https://developer.mozilla.org/en/Plugins">Mozilla's +NPAPI plugin reference</a> for information on how to do that. +</p> + +<p> +Once you have an NPAPI plugin, +follow these steps to get your extension using it. +</p> + +<ol> + <li> + Add a section to your extension's <code>manifest.json</code> + that describes where to find the plugin, + along with other properties about it: + +<pre>{ + "name": "My extension", + ... + <b>"plugins": [ + { "path": "content_plugin.dll", "public": true }, + { "path": "extension_plugin.dll" } + ]</b>, + ... +}</pre> + + <p> + The "path" property specifies the path to your plugin, + relative to the manifest file. + The "public" property specifies whether + your plugin can be accessed by regular web pages; + the default is false, + meaning only your extension can load the plugin. + </p> + </li> + + <li> + Create an HTML file that loads your plugin by mime-type. + Assuming your mime-type is "application/x-my-extension": + +<pre> +<embed type="application/x-my-extension" id="pluginId"></embed> +<script> + var plugin = document.getElementById("pluginId"); + var result = plugin.myPluginMethod(); // call a method in your plugin + console.log("my plugin returned: " + result); +</script></pre> + + <p> + This can be inside a background page + or any other HTML page used by your extension. + If your plugin is "public", + you can even use a content script to programmatically + insert your plugin into a web page. + </p> + </li> +</ol> + +<h2 id="security-considerations">Security considerations</h2> + +<p> +Including an NPAPI plugin in your extension is dangerous because plugins +have unrestricted access to the local machine. If your plugin contains +a vulnerability, an attacker might be able to exploit that vulnerability +to install malicious software on the user's machine. Instead, avoid +including an NPAPI plugin whenever possible. +</p> + +<p> +Marking your NPAPI plugin "public" increase the attack surface of your +extension because the plugin is exposed directly to web content, making +it easier for a malicious web site to manipulate your plugin. Instead, +avoid making your NPAPI plugin public whenever possible. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/offline_apps.html b/chrome/common/extensions/docs/templates/articles/offline_apps.html new file mode 100644 index 0000000..0f62202 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/offline_apps.html @@ -0,0 +1,313 @@ +<h1>Offline First</h1> + + +<p> +Because internet connections can be flakey or non-existent, +you need to consider <em>offline first</em>: +write your app as if it has no internet connection. +Once your app works offline, +add whatever network functionality you need +for your app to do more when it’s online. +Read on for tips on implementing your offline-enabled app. +</p> + +<h2 id="overview"> Overview </h2> + +<p> +Packaged apps get the following for free: +</p> + +<ul> + <li> Your app’s files—all of its JavaScript, + CSS, and fonts, plus other resources it needs + (such as images)—are <b>already downloaded</b>. </li> + <li> Your app can <b>save and optionally sync</b> + small amounts of data using the + <a href="storage.html">Chrome Storage API</a>. </li> + <li> Your app can <b>detect changes in connectivity</b> + by listening for + <a href="https://developer.mozilla.org/en/Online_and_offline_events">online and offline events</a>. </li> +</ul> + +<p> +But those abilities aren't enough to guarantee that your app +will work offline. +Your offline-enabled app should follow these rules: +</p> + +<dl> + <dt> Use local data whenever possible. </dt> + <dd> When using resources from the internet, + use <code>XMLHttpRequest</code> to get it, + and then save the data locally. + You can use the Chrome Storage API, + IndexedDB, or + Filesystem API to save data locally. </dd> + + <dt> Separate your app’s UI from its data. </dt> + <dd> + Separating the UI and data not only + improves your app's design and + eases the task of enabling offline usage, + but also lets you provide other views of the user's data. + An MVC framework can help you keep the UI and data separate. + </dd> + + <dt> Assume your app can be closed at any time. </dt> + <dd> Save application state + (both locally and remotely, when possible) + so that users can pick up + wherever they left off. </dd> + + <dt> Test your app thoroughly. </dt> + <dd> Make sure your app works well in both + <a href="#testing">common and tricky scenarios</a>. </dd> +</dl> + + +<h2 id="possibilities"> Security restrictions </h2> + +<p> + Packaged apps are limited + in where they can place their resources: +</p> + +<ul> + <li> + Because local data + is visible on the user's machine + and can't be securely encrypted, + <b>sensitive data must stay on the server</b>. + For example, don't store passwords or credit card numbers locally. + </li> + <li> All <b>JavaScript</b> that the app executes + must be in the app's package. + It <b>cannot</b> be inline. + <br /> + <span class="comment"> + {PENDING: Should "JavaScript" be "executable code"? + What about NaCl and Dart? Anything else -- shaders, e.g.?} + </span> + </li> + <li> All <b>CSS styles</b>, <b>images</b>, and <b>fonts</b> + can be initially located + either in the app's package + or at a remote URL. + If the resource is remote, + you can't specify it in your HTML. + Instead, get the data using <code>XMLHttpRequest</code> + (see <a href="app_external.html#external">Referencing external resources</a>). + Then either refer to the data with a blob URL + or (better yet) save and then load the data using the + <a href="app_storage.html">Filesystem API</a>. + + <p class="note"> + <b>Note:</b> + Styles can be inline or in separate <code>.css</code> files. + </p> + + </li> +</ul> + +<p> +You can, however, +load large media resources such as videos and sounds +from external sites. +One reason for this exception to the rule +is that the <video> and <audio> elements +have good fallback behavior when an app +has limited or no connectivity. +Another reason is that fetching and serving media +with <code>XMLHttpRequest</code> and blob URLs +currently does not allow +streaming or partial buffering. +</p> + +<p> +To provide a sandboxed iframe, +you can create an <object> tag. +Its contents can be remote, +but it has no direct access to the Chrome app APIs +(see <a href="app_external.html#objecttag">Embed external web pages</a>). +</p> + +<p> +Some of the restrictions on packaged apps are enforced by the +<a href="app_csp.html">Content Security Policy (CSP)</a> +which is always the following and cannot be changed for packaged apps: +</p> + +<pre> +default-src 'self'; +connect-src *; +style-src 'self' blob: data: filesystem: 'unsafe-inline'; +img-src 'self' blob: data: filesystem:; +frame-src 'self' blob: data: filesystem:; +font-src 'self' blob: data: filesystem:; +media-src *; +</pre> + +<h2 id="manifest"> Specifying offline_enabled </h2> + +<p> +It is assumed that your app behaves well offline. If it doesn't, you should +advertise that fact, so that its launch icon is dimmed when the user is offline. +To do so, set <code>offline_enabled</code> to <code>false</code> in the +<a href="manifest.html">app manifest file</a>: +</p> + +<pre> +{ + "name": "My app", + ... + <b>"offline_enabled": false,</b> + ... +} +</pre> + +<p class="comment"> +{PENDING: should we link to <a href="https://chrome.google.com/webstore/category/collection/offline_enabled">Offline Apps collection</a>? +show a screenshot of how offline apps are highlighted? +anything else?} +</p> + +<h2 id="saving-locally"> Saving data locally </h2> + +<p> +The following table shows your options for saving data locally +(see also <a href="app_storage.html">Manage Data</a>). +</p> + +<table> +<tr> + <th> API </th> <th> Best use </th> <th> Notes </th> +</tr> +<tr> + <td> Chrome Storage API </td> + <td> Small amounts of string data </td> + <td> Great for settings and state. + Easy to sync remotely (but you don't have to). + Not good for larger amounts of data, + due to quotas. + </td> +</tr> +<tr> + <td> IndexedDB API </td> + <td> Structured data </td> + <td> Enables fast searches on data. + Use with the + <a href="manifest.html#permissions">unlimitedStorage permission</a>. </td> +</tr> +<tr> + <td> Filesystem API </td> + <td> Anything else </td> + <td> Provides a sandboxed area where you can store files. + Use with the + <a href="manifest.html#permissions">unlimitedStorage permission</a>. </td> +</tr> +</table> + +<p class="note"> +<b>Note:</b> +Packaged apps cannot use Web SQL Database or localStorage. +The WebSQL specification has been deprecated for awhile now, +and localStorage handles data synchronously +(which means it can be slow). +The Storage API handles data asynchronously. +</p> + + +<h2 id="saving-remotely"> Saving data remotely </h2> + +<p> +In general, how you save data remotely is up to you, +but some frameworks and APIs can help +(see <a href="app_frameworks.html">MVC Architecture</a>). +If you use the Chrome Storage API, +then all syncable data +is automatically synced +whenever the app is online +and the user is signed in to Chrome. +If the user isn't signed in, +they'll be prompted to sign in. +However, note that the user's synced data +is deleted if the user uninstalls your app. +<span class="comment"> +{QUESTION: true?} +</span> +</p> + +<p> +Consider saving users' data for at least +30 days after your app is uninstalled, +so that users will have a good experience +if they reinstall your app. +</p> + + +<h2 id="mvc"> Separating UI from data </h2> + +<p> +Using an MVC framework can help you design and implement your app +so that the data is completely separate from the app's +view on the data. +See <a href="app_frameworks.html">MVC Architecture</a> +for a list of MVC frameworks. +</p> + +<p> +If your app talks to a custom server, +the server should give you data, +not chunks of HTML. +Think in terms of RESTful APIs. +</p> + +<p> +Once your data is separate from your app, +it's much easier to provide alternate views of the data. +For example, +you might provide a website view of any public data. +Not only can a website view +be useful when your user is away from Chrome, +but it can enable search engines to find the data. +</p> + + +<h2 id="testing"> Testing </h2> + +<p> +Make sure your app works well under the following circumstances: +</p> + +<ul> + <li> + The app is installed, and then immediately goes offline. + In other words, the first use of the app is offline. + </li> + <li> + The app is installed on one computer + and then synced to another. + </li> + <li> + The app is uninstalled and then immediately installed again. + </li> + <li> + The app is running on two computers at the same time, + with the same profile. + The app must behave reasonably + when one computer goes offline, + the user does a bunch of stuff on that computer, + and then the computer comes online again. + </li> + <li> + The app has intermittent connectivity, + switching often between online and offline. + </li> +</ul> + +<p> +Also make sure that the app saves <b>no sensitive user data</b> +(such as passwords) on the user's machine. +</p> + +<p class="backtotop"><a href="#top">Back to top</a></p> diff --git a/chrome/common/extensions/docs/templates/articles/options.html b/chrome/common/extensions/docs/templates/articles/options.html new file mode 100644 index 0000000..11ee005 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/options.html @@ -0,0 +1,79 @@ +<h1>Options</h1> + +<p>To allow users to customize the behavior of your extension, you may wish to provide an options page. If you do, a link to it will be provided from the extensions management page at chrome://extensions. Clicking the Options link opens a new tab pointing at your options page. + +<h2>Step 1: Declare your options page in the manifest</h2> + +<pre>{ + "name": "My extension", + ... + <b>"options_page": "options.html"</b>, + ... +}</pre> + + +<h2>Step 2: Write your options page</h2> + +Here is an example options page: + +<pre>// Save this script as `options.js` + +// Saves options to localStorage. +function save_options() { + var select = document.getElementById("color"); + var color = select.children[select.selectedIndex].value; + localStorage["favorite_color"] = color; + + // Update status to let user know options were saved. + var status = document.getElementById("status"); + status.innerHTML = "Options Saved."; + setTimeout(function() { + status.innerHTML = ""; + }, 750); +} + +// Restores select box state to saved value from localStorage. +function restore_options() { + var favorite = localStorage["favorite_color"]; + if (!favorite) { + return; + } + var select = document.getElementById("color"); + for (var i = 0; i < select.children.length; i++) { + var child = select.children[i]; + if (child.value == favorite) { + child.selected = "true"; + break; + } + } +} +document.addEventListener('DOMContentReady', restore_options); +document.querySelector('#save').addEventListener('click', save_options); +</pre> + +<pre> +<html> +<head><title>My Test Extension Options</title></head> +<script src="options.js"> + +<body> + +Favorite Color: +<select id="color"> + <option value="red">red</option> + <option value="green">green</option> + <option value="blue">blue</option> + <option value="yellow">yellow</option> +</select> + +<br> +<div id="status"></div> +<button id="save">Save</button> +</body> +</html> +</pre> + +<h2>Important notes</h2> +<ul> +<li>We plan on providing some default css styles to encourage a consistent look across different extensions' options pages. You can star <a href="http://crbug.com/25317">crbug.com/25317</a> to be notified of updates.</li> +</ul>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/override.html b/chrome/common/extensions/docs/templates/articles/override.html new file mode 100644 index 0000000..b5e0015 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/override.html @@ -0,0 +1,187 @@ +<h1>Override Pages</h1> + + +<style> +#pics { + margin:2em 1em 1.5em; +} + +#pics td { + text-align:center; + width:50%!important; + border:none; + padding:0 1em; + font-size:90%; +} + +#pics img { + width:188; + height:246; + border:none; +} +</style> + +<p> +Override pages are a way to substitute an HTML file from your extension +for a page that Google Chrome normally provides. +In addition to HTML, +an override page usually has CSS and JavaScript code. +</p> + +<p> +An extension can replace any one of the following pages: +<ul> + <li> <b>Bookmark Manager:</b> + The page that appears when the user chooses + the Bookmark Manager menu item + from the wrench menu or, on Mac, + the Bookmark Manager item from the Bookmarks menu. + You can also get to this page by entering the URL + <b>chrome://bookmarks</b>. + </li> + + <li> <b>History:</b> + The page that appears when the user + chooses the History menu item + from the Tools (wrench) menu or, on Mac, + the Show Full History item from the History menu. + You can also get to this page by entering the URL + <b>chrome://history</b>. + </li> + + <li> <b>New Tab:</b> + The page that appears when the user creates a new tab or window. + You can also get to this page by entering the URL + <b>chrome://newtab</b>. + </li> +</ul> +</p> + +<p class="note"> +<b>Note:</b> +A single extension can override +<b>only one page</b>. +For example, an extension can't override both +the Bookmark Manager and History pages. +</p> + +<p> +Incognito windows are treated specially. +New Tab pages cannot be overridden in incognito windows. +Other override pages work in incognito windows +as long as the +<a href="manifest.html#incognito">incognito</a> +manifest property is set to "spanning" +(which is the default value for extensions +but not for packaged apps). +See <a href="overview.html#incognito">Saving data and incognito mode</a> +in the Overview for more details on how you should treat +incognito windows. +</p> + +<p> +The following screenshots show the default New Tab page +next to a custom New Tab page. +</p> + +<table id="pics"> + <tr> + <td> <b>The default New Tab page</b> </td> + <td> <b>An alternative New Tab page</b> </td> + </tr> + <tr> + <td> + <img src="{{static}}/images/ntp-default.png" + alt="default New Tab page" + width="200" height="173"> + </td> + <td> + <img src="{{static}}/images/ntp-blank.png" + alt="a blank New Tab page" + width="200" height="173"> + </td> + </tr> +</table> + +<h2 id="manifest">Manifest</h2> + +<p> +Register an override page in the +<a href="manifest.html">extension manifest</a> like this: +</p> + +<pre>{ + "name": "My extension", + ... + +<b> "chrome_url_overrides" : { + "<em>pageToOverride</em>": "<em>myPage.html</em>" + }</b>, + ... +}</pre> + +<p> +For <code><em>pageToOverride</em></code>, substitute one of the following: +</p> + +<ul> + <li> <code>bookmarks</code> + <li> <code>history</code> + <li> <code>newtab</code> +</ul> + + +<h2 id="tips">Tips</h2> + +<p> +For an effective override page, follow these guidelines: +</p> + +<ul> + <li> + <p> + <b>Make your page quick and small.</b> <br /> + Users expect built-in browser pages to open instantly. + Avoid doing things that might take a long time. + For example, avoid synchronous fetches of network or database resources. + </p> + </li> + <li> + <p> + <b>Include a title in your page.</b> <br /> + Otherwise people might see the URL of the page, + which could be confusing. + Here's an example of specifying the title: + <code><title>New Tab</title></code> + </p> + </li> + <li> + <p> + <b>Don't rely on the page having the keyboard focus.</b> <br /> + The address bar always gets the focus first + when the user creates a new tab. + </p> + </li> + <li> + <p> + <b>Don't try to emulate the default New Tab page.</b> <br /> + The APIs necessary to create + a slightly modified version of the default New Tab page — + with top pages, + recently closed pages, + tips, + a theme background image, + and so on — + don't exist yet. + Until they do, + you're better off trying to make something completely different. + </p> + </li> +</ul> + +<h2 id="examples"> Examples </h2> + +<p> +See the +<a href="samples.html#chrome_url_overrides">override samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/overview.html b/chrome/common/extensions/docs/templates/articles/overview.html new file mode 100644 index 0000000..bbc7935 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/overview.html @@ -0,0 +1,642 @@ +<h1>Overview</h1> + + +<p> +Once you've finished this page +and the +<a href="getstarted.html">Getting Started</a> tutorial, +you'll be all set to start writing extensions and packaged apps. +</p> + +<p class="caution"> +<strong>Note:</strong> +<em>Packaged apps</em> are implemented as extensions, +so unless otherwise stated, +everything in this page applies to packaged apps. +</p> + +<h2 id="what">The basics</h2> + +<p> +An extension is a zipped bundle of files—HTML, +CSS, JavaScript, images, and anything else you need—that +adds functionality to the Google Chrome browser. +Extensions are essentially web pages, +and they can use all the +<a href="api_other.html">APIs that the browser provides to web pages</a>, +from XMLHttpRequest to JSON to HTML5. +</p> + +<p> +Extensions can interact with web pages or servers using +<a href="content_scripts.html">content scripts</a> or +<a href="xhr.html">cross-origin XMLHttpRequests</a>. +Extensions can also interact programmatically +with browser features such as +<a href="bookmarks.html">bookmarks</a> +and <a href="tabs.html">tabs</a>. +</p> + +<h3 id="extension-ui">Extension UIs</h3> + +<p> +Many extensions—but not packaged apps—add +UI to Google Chrome in the form of +<a href="browserAction.html">browser actions</a> +or <a href="pageAction.html">page actions</a>. +Each extension can have at most one browser action or page action. +Choose a <b>browser action</b> when the extension is relevant to most pages. +Choose a <b>page action</b> when the extension's icon +should appear or disappear, +depending on the page. +</p> + +<table class="columns"> +<tr> + <td width="33%"> + <img src="{{static}}/images/overview/browser-action.png" + width="147" height="100" + alt="screenshot" /> + </td> + <td width="33%"> + <img src="{{static}}/images/overview/page-action.png" + width="147" height="100" + alt="screenshot" /> + </td> + <td> + <img src="{{static}}/images/overview/browser-action-with-popup.png" + width="147" height="100" + alt="screenshot" /> + </td> +</tr> + +<tr> + <td> + This <a href="samples.html#gmail">mail extension</a> + uses a <em>browser action</em> + (icon in the toolbar). + </td> + <td> + This <a href="samples.html#mappy">map extension</a> + uses a <em>page action</em> + (icon in the address bar) + and <em>content script</em> + (code injected into a web page). + </td> + <td> + This <a href="samples.html#news">news extension</a> + features a browser action that, + when clicked, + shows a <em>popup</em>. + </td> +</tr> +</table> + +<p> +Extensions (and packaged apps) can also present a UI in other ways, +such as adding to the Chrome context menu, +providing an options page, +or using a content script that changes how pages look. +See the <a href="devguide.html">Developer's Guide</a> +for a complete list of extension features, +with links to implementation details +for each one. +</p> + + +<h3 id="packagedapp-ui">Packaged app UIs</h3> + +<p> +A packaged app usually presents its main functionality using +an HTML page that's bundled into the app. +For example, the following packaged app +displays a Flash file within an HTML page. +</p> + +<img src="{{static}}/images/overview/flash-app.png" + width="372" height="300" + alt="screenshot" /> + +<p> +For more information, +see <a href="apps.html">Packaged Apps</a>. +</p> + +<h2 id="files">Files</h2> +<p> +Each extension has the following files: + +</p> + +<ul> + <li>A <b>manifest file</b></li> + <li>One or more <b>HTML files</b> (unless the extension is a theme)</li> + <li><em>Optional:</em> One or more <b>JavaScript files</b></li> + <li><em>Optional:</em> Any other files your extension needs—for + example, image files</li> +</ul> + +<p> +While you're working on your extension, +you put all these files into a single folder. +When you distribute your extension, +the contents of the folder are packaged into a special ZIP file +that has a <code>.crx</code> suffix. +If you upload your extension using the +<a href="https://chrome.google.com/webstore/developer/dashboard">Chrome Developer Dashboard</a>, +the <code>.crx</code> file is created for you. +For details on distributing extensions, +see <a href="hosting.html">Hosting</a>. +</p> + + +<h3 id="relative-urls">Referring to files</h3> + +<p> +You can put any file you like into an extension, +but how do you use it? +Usually, +you can refer to the file using a relative URL, +just as you would in an ordinary HTML page. +Here's an example of referring to +a file named <code>myimage.png</code> +that's in a subfolder named <code>images</code>. +</p> + +<pre> +<img <b>src="images/myimage.png"</b>> +</pre> + +<p> +As you might notice while you use the Google Chrome debugger, +every file in an extension is also accessible by an absolute URL like this: +</p> + +<blockquote> +<b>chrome-extension://</b><em><extensionID></em><b>/</b><em><pathToFile></em> +</blockquote> + +<p> +In that URL, the <em><extensionID></em> is a unique identifier +that the extension system generates for each extension. +You can see the IDs for all your loaded extensions +by going to the URL <b>chrome://extensions</b>. +The <em><pathToFile></em> is the location of the file +under the extension's top folder; +it's the same as the relative URL. +</p> + +<p> +While you're working on an extension +(before it's packaged), +the extension ID can change. +Specifically, the ID of an unpacked extension will change +if you load the extension from a different directory; +the ID will change again when you package the extension. +If your extension's code +needs to specify the full path to a file within the extension, +you can use the <code>@@extension_id</code> +<a href="i18n.html#overview-predefined">predefined message</a> +to avoid hardcoding the ID during development. +</p> + +<p> +When you package an extension +(typically, by uploading it with the dashboard), +the extension gets a permanent ID, +which remains the same even after you update the extension. +Once the extension ID is permanent, +you can change all occurrences of +<code>@@extension_id</code> to use the real ID. +</p> + + +<h3>The manifest file</h3> + +<p> +The manifest file, called <code>manifest.json</code>, +gives information about the extension, +such as the most important files +and the capabilities that the extension might use. +Here's a typical manifest file for a browser action +that uses information from google.com: +</p> + +<pre> +{ + "name": "My Extension", + "version": "2.1", + "description": "Gets information from Google.", + "icons": { "128": "icon_128.png" }, + "background": { + "persistent": false, + "scripts": ["bg.js"] + }, + "permissions": ["http://*.google.com/", "https://*.google.com/"], + "browser_action": { + "default_title": "", + "default_icon": "icon_19.png", + "default_popup": "popup.html" + } +}</pre> + +<p> +For details, see +<a href="manifest.html">Manifest Files</a>. +</p> + +<h2 id="arch">Architecture</h2> + +<p> +Many extensions have a <em>background page</em>, +an invisible page +that holds the main logic of the extension. +An extension can also contain other pages +that present the extension's UI. +If an extension needs to interact with web pages that the user loads +(as opposed to pages that are included in the extension), +then the extension must use a content script. +</p> + + +<h3 id="background_page">The background page</h3> + +<p> +The following figure shows a browser +that has at least two extensions installed: +a browser action (yellow icon) +and a page action (blue icon). +Both the browser action and the page action +have background pages. +This figure shows the browser action's background page, +which is defined by <code>background.html</code> +and has JavaScript code that controls +the behavior of the browser action in both windows. +</p> + +<img src="{{static}}/images/overview/arch-1.gif" + width="232" height="168" + alt="Two windows and a box representing a background page (background.html). One window has a yellow icon; the other has both a yellow icon and a blue icon. The yellow icons are connected to the background page." /> + +<p> +There are two types of background pages: +<a href="background_pages.html">persistent background pages</a>, +and <a href="event_pages.html">event pages</a>. Persistent +background pages, as the name suggests, are always open. +Event pages are opened and closed as needed. Unless you absolutely +need your background page to run all the time, prefer to use +an event page. +</p> + +<!-- PENDING: Perhaps show a picture of many background page processes. + This could build on a figure that shows the process architecture, + and perhaps the differences between packaged apps and extensions. --> + +<p> +See <a href="event_pages.html">Event Pages</a> +and <a href="background_pages.html">Background Pages</a> +for more details. +</p> + +<h3 id="pages">UI pages</h3> + +<p> +Extensions can contain ordinary HTML pages that display the extension's UI. +For example, a browser action can have a popup, +which is implemented by an HTML file. +Any extension can have an options page, +which lets users customize how the extension works. +Another type of special page is the override page. +And finally, you can +use <a href="tabs.html#method-create">chrome.tabs.create()</a> +or <code>window.open()</code> +to display any other HTML files that are in the extension. +</p> + +<p> +The HTML pages inside an extension +have complete access to each other's DOMs, +and they can invoke functions on each other. +</p> + +<!-- PENDING: Change the following example and figure +to use something that's not a popup? +(It might lead people to think that popups need background pages.) --> + +<p> +The following figure shows the architecture +of a browser action's popup. +The popup's contents are a web page +defined by an HTML file +(<code>popup.html</code>). +This extension also happens to have a background page +(<code>background.html</code>). +The popup doesn't need to duplicate code +that's in the background page +because the popup can invoke functions on the background page. +</p> + +<img src="{{static}}/images/overview/arch-2.gif" + width="256" height="168" + alt="A browser window containing a browser action that's displaying a popup. The popup's HTML file (popup.html) can communicate with the extension's background page (background.html)." /> + +<p> +See <a href="browserAction.html">Browser Actions</a>, +<a href="options.html">Options</a>, +<a href="override.html">Override Pages</a>, +and the <a href="#pageComm">Communication between pages</a> section +for more details. +</p> + + +<h3 id="contentScripts">Content scripts</h3> + +<p> +If your extension needs to interact with web pages, +then it needs a <em>content script</em>. +A content script is some JavaScript +that executes in the context of a page +that's been loaded into the browser. +Think of a content script as part of that loaded page, +not as part of the extension it was packaged with +(its <em>parent extension</em>). +</p> + +<!-- [PENDING: Consider explaining that the reason content scripts are separated from the extension is due to chrome's multiprocess design. Something like: + +Each extension runs in its own process. +To have rich interaction with a web page, however, +the extension must be able to +run some code in the web page's process. +Extensions accomplish this with content scripts.] +--> + +<p> +Content scripts can read details of the web pages the browser visits, +and they can make changes to the pages. +In the following figure, +the content script +can read and modify +the DOM for the displayed web page. +It cannot, however, modify the DOM of its parent extension's background page. +</p> + +<img src="{{static}}/images/overview/arch-3.gif" + width="238" height="169" + alt="A browser window with a browser action (controlled by background.html) and a content script (controlled by contentscript.js)." /> + +<p> +Content scripts aren't completely cut off from their parent extensions. +A content script can exchange messages with its parent extension, +as the arrows in the following figure show. +For example, a content script might send a message +whenever it finds an RSS feed in a browser page. +Or a background page might send a message +asking a content script to change the appearance of its browser page. +</p> + +<img src="{{static}}/images/overview/arch-cs.gif" + width="238" height="194" + alt="Like the previous figure, but showing more of the parent extension's files, as well as a communication path between the content script and the parent extension." /> + + + +<p> +For more information, +see <a href="content_scripts.html">Content Scripts</a>. +</p> + + +<h2 id="apis"> Using the chrome.* APIs </h2> + +<p> +In addition to having access to all the APIs that web pages and apps can use, +extensions can also use Chrome-only APIs +(often called <em>chrome.* APIs</em>) +that allow tight integration with the browser. +For example, any extension or web app can use the +standard <code>window.open()</code> method to open a URL. +But if you want to specify which window that URL should be displayed in, +your extension can use the Chrome-only +<a href="tabs.html#method-create">chrome.tabs.create()</a> +method instead. +</p> + +<h3 id="sync"> Asynchronous vs. synchronous methods </h3> +<p> +Most methods in the chrome.* APIs are <b>asynchronous</b>: +they return immediately, without waiting for the operation to finish. +If you need to know the outcome of that operation, +then you pass a callback function into the method. +That callback is executed later (potentially <em>much</em> later), +sometime after the method returns. +Here's an example of the signature for an asynchronous method: +</p> + +<p> +<code> +chrome.tabs.create(object <em>createProperties</em>, function <em>callback</em>) +</code> +</p> + +<p> +Other chrome.* methods are <b>synchronous</b>. +Synchronous methods never have a callback +because they don't return until they've completed all their work. +Often, synchronous methods have a return type. +Consider the +<a href="runtime.html#method-getURL">chrome.runtime.getURL()</a> method: +</p> + +<p> +<code> +string chrome.runtime.getURL() +</code> +</p> + +<p> +This method has no callback and a return type of <code>string</code> +because it synchronously returns the URL +and performs no other, asynchronous work. +</p> + + +<h3 id="sync-example"> Example: Using a callback </h3> + +<p> +Say you want to navigate +the user's currently selected tab to a new URL. +To do this, you need to get the current tab's ID +(using <a href="tabs.html#method-getSelected">chrome.tabs.getSelected()</a>) +and then make that tab go to the new URL +(using <a href="tabs.html#method-update">chrome.tabs.update()</a>). +</p> + +<p> +If <code>getSelected()</code> were synchronous, +you might write code like this: +</p> + +<pre> + <b>//THIS CODE DOESN'T WORK</b> +<span class="linenumber">1: </span>var tab = chrome.tabs.getSelected(null); <b>//WRONG!!!</b> +<span class="linenumber">2: </span>chrome.tabs.update(tab.id, {url:newUrl}); +<span class="linenumber">3: </span>someOtherFunction(); +</pre> + +<p> +That approach fails +because <code>getSelected()</code> is asynchronous. +It returns without waiting for its work to complete, +and it doesn't even return a value +(although some asynchronous methods do). +You can tell that <code>getSelected()</code> is asynchronous +by the <em>callback</em> parameter in its signature: + +<p> +<code> +chrome.tabs.getSelected(integer <em>windowId</em>, function <em>callback</em>) +</code> +</p> + +<p> +To fix the preceding code, +you must use that callback parameter. +The following code shows +how to define a callback function +that gets the results from <code>getSelected()</code> +(as a parameter named <code>tab</code>) +and calls <code>update()</code>. +</p> + +<pre> + <b>//THIS CODE WORKS</b> +<span class="linenumber">1: </span>chrome.tabs.getSelected(null, <b>function(tab) {</b> +<span class="linenumber">2: </span> chrome.tabs.update(tab.id, {url:newUrl}); +<span class="linenumber">3: </span><b>}</b>); +<span class="linenumber">4: </span>someOtherFunction(); +</pre> + +<p> +In this example, the lines are executed in the following order: 1, 4, 2. +The callback function specified to <code>getSelected</code> is called +(and line 2 executed) +only after information about the currently selected tab is available, +which is sometime after <code>getSelected()</code> returns. +Although <code>update()</code> is asynchronous, +this example doesn't use its callback parameter, +since we don't do anything about the results of the update. +</p> + + +<h3 id="chrome-more"> More details </h3> + +<p> +For more information, see the +<a href="api_index.html">chrome.* API docs</a> +and watch this video: +</p> + +<p> +<iframe title="YouTube video player" width="640" height="390" src="http://www.youtube.com/embed/bmxr75CV36A?rel=0" frameborder="0" allowfullscreen></iframe> +</p> + +<h2 id="pageComm">Communication between pages </h2> + +<p> +The HTML pages within an extension often need to communicate. + +Because all of an extension's pages +execute in same process on the same thread, +the pages can make direct function calls to each other. +</p> + +<p> +To find pages in the extension, use +<a href="extension.html"><code>chrome.extension</code></a> +methods such as +<code>getViews()</code> and +<code>getBackgroundPage()</code>. +Once a page has a reference to other pages within the extension, +the first page can invoke functions on the other pages, +and it can manipulate their DOMs. +</p> + + + + +<h2 id="incognito"> Saving data and incognito mode </h2> + +<p> +Extensions can save data using +the HTML5 <a href="http://dev.w3.org/html5/webstorage/">web storage API</a> +(such as <code>localStorage</code>) +or by making server requests that result in saving data. +Whenever you want to save something, +first consider whether it's +from a window that's in incognito mode. +By default, extensions don't run in incognito windows, +and packaged apps <em>do</em>. +You need to consider what a user expects +from your extension or packaged app +when the browser is incognito. +</p> + +<p> +<em>Incognito mode</em> promises that the window will leave no tracks. +When dealing with data from incognito windows, +do your best to honor this promise. +For example, if your extension normally +saves browsing history to the cloud, +don't save history from incognito windows. +On the other hand, you can store +your extension's settings from any window, +incognito or not. +</p> + +<p class="note"> +<b>Rule of thumb:</b> +If a piece of data might show where a user +has been on the web or what the user has done, +don't store it if it's from an incognito window. +</p> + +<p> +To detect whether a window is in incognito mode, +check the <code>incognito</code> property of the relevant +<a href="tabs.html#type-Tab">Tab</a> or +<a href="windows.html#type-Window">Window</a> object. +For example: +</p> + +<pre> +function saveTabData(tab, data) { + if (tab.incognito) { + chrome.runtime.getBackgroundPage(function(bgPage) { + bgPage[tab.url] = data; // Persist data ONLY in memory + }); + } else { + localStorage[tab.url] = data; // OK to store data + } +} +</pre> + + +<h2 id="now-what"> Now what? </h2> + +<p> +Now that you've been introduced to extensions, +you should be ready to write your own. +Here are some ideas for where to go next: +</p> + +<ul> + <li> <a href="getstarted.html">Tutorial: Getting Started</a> </li> + <li> <a href="tut_debugging.html">Tutorial: Debugging</a> </li> + <li> <a href="devguide.html">Developer's Guide</a> </li> + <li> <a href="http://dev.chromium.org/developers/design-documents/extensions/samples">Samples</a> </li> + <li> <a href="http://www.youtube.com/view_play_list?p=CA101D6A85FE9D4B">Videos</a>, + such as + <a href="http://www.youtube.com/watch?v=B4M_a7xejYI&feature=PlayList&p=CA101D6A85FE9D4B&index=6">Extension Message Passing</a> + </li> +</ul> diff --git a/chrome/common/extensions/docs/templates/articles/packaging.html b/chrome/common/extensions/docs/templates/articles/packaging.html new file mode 100644 index 0000000..7e47f19 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/packaging.html @@ -0,0 +1,195 @@ +<h1>Packaging</h1> + + +<p> +This page describes how to package your extension. +As the <a href="overview.html">Overview</a> explains, +extensions are packaged as signed ZIP files +with the file extension "crx"—for example, +<code>myextension.crx</code>. +</p> + +<p> +<b>Note:</b> +You do not need to package your own extension. +If you publish your extension using the +<a href="https://chrome.google.com/webstore/developer/dashboard">Chrome Developer Dashboard</a>, +then the only reason to create your own <code>.crx</code> file +would be to distribute a non-public version—for example, +to alpha testers. +You can find information on publishing extensions and apps in the +Chrome Web Store getting started tutorial, starting at +<a href="http://code.google.com/chrome/webstore/docs/get_started_simple.html#step5">Step 5: Zip up your app</a>. +</p> + +<p> +When you package an extension, +the extension is assigned a unique key pair. +The extension's ID is based on a hash of the public key. +The private key is used to sign each version of the extension +and must be secured from public access. +Be careful not to include your private key within +your extensions! +</p> + + +<h2>Creating a package</h2> + +<p>To package an extension:</p> +<ol> + <li> + Bring up the Extensions management page + by going to this URL: + <blockquote> + <b>chrome://extensions</b> + </blockquote> + </li> + + <li> + If <b>Developer mode</b> has a + by it, + click the +. + </li> + + <li> + Click the <b>Pack extension</b> button. + A dialog appears. + </li> + + <li> + In the <b>Extension root directory</b> field, + specify the path to the extension's folder—for example, + <code>c:\myext</code>. + (Ignore the other field; + you don't specify a private key file + the first time you package a particular extension.) + </li> + + <li> + Click <b>OK</b>. + The packager creates two files: + a <code>.crx</code> file, + which is the actual extension that can be installed, + and a <code>.pem</code> file, + which contains the private key. + </li> +</ol> + + +<p> +<b>Do not lose the private key!</b> +Keep the <code>.pem</code> file secret and in a safe place. +You'll need it later if you want to do any of the following: +</p> +<ul> +<li><a href="#update">Update</a> the extension</li> +<li><a href="#upload">Upload</a> the extension to the Chrome Web Store</li> +</ul> + +<p> +If the extension is successfully packaged, you'll see a dialog like this +that tells you where to find +the <code>.crx</code> and <code>.pem</code> files:</p> +</p> + +<img src="{{static}}/images/package-success.gif" + width="554" height="208" /> + + +<h2 id="update">Updating a package</h2> + +<p>To create an updated version of your extension:</p> +<ol> + <li> + Increase the version number in <code>manifest.json</code>. + </li> + + <li> + Bring up the Extensions management page + by going to this URL: <b>chrome://extensions</b> + </li> + + <li> + Click the <b>Pack extension</b> button. + A dialog appears. + </li> + + <li> + In the <b>Extension root directory</b> field, + specify the path to the extension's folder—for example, + <code>c:\myext</code>. + </li> + + <li> + In the <b>Private key file</b> field, + specify the location of the + already generated <code>.pem</code> file for this extension—for + example, <code>c:\myext.pem</code>. + </li> + + <li> + Click <b>OK</b>. + </li> +</ol> + +<p>If the updated extension is successfully packaged, you'll see a dialog like this:</p> + +<img src="{{static}}/images/update-success.gif" + width="298" height="160" /> + + +<h2 id="upload"> Uploading a previously packaged extension to the Chrome Web Store</h2> + +<p> +You can use the Chrome Developer Dashboard +to upload an extension that you've previously packaged yourself. +However, unless you take special steps, +the extension's ID in the Chrome Web Store +will be different from its ID in the package you created. +This different ID might be a problem if you've +distributed your extension package, +because it allows users to install multiple versions of your extension, +each with its own local data. +</p> + +<p> +If you want to keep the extension ID the same, +follow these steps: +</p> + +<ol> + <li> Rename the private key that was generated + when you created the <code>.crx</code> file to <code>key.pem</code>. </li> + <li> Put <code>key.pem</code> in the top directory + of your extension. </li> + <li> Compress that directory into a ZIP file. </li> + <li> Upload the ZIP file using the + <a href="https://chrome.google.com/webstore/developer/dashboard">Chrome Developer Dashboard</a>. </li> +</ol> + + +<h2>Packaging at the command line</h2> + +<p> +Another way to package extensions +is by invoking <code>chrome.exe</code> at the command line. +Use the <code>--pack-extension</code> flag +to specify the location of the extension's folder. +Use <code>--pack-extension-key</code> +to specify the location of the extension's private key file. +For example: +</p> + +<pre> +chrome.exe --pack-extension=c:\myext --pack-extension-key=c:\myext.pem +</pre> + +<p> +To suppress the dialog, +add <code>--no-message-box</code> to the command. +</p> + +<h2>Package format and scripts</h2> +<p> +For more information on the format, as well as pointers to scripts you can use +to create <code>.crx</code> files, see <a href="crx.html">CRX Package Format</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/permission_warnings.html b/chrome/common/extensions/docs/templates/articles/permission_warnings.html new file mode 100644 index 0000000..a5e0780 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/permission_warnings.html @@ -0,0 +1,449 @@ +<h1>Permission Warnings</h1> + + +<!-- +NOTE: When this doc is updated, the online help should also be updated: +http://www.google.com/support/chrome_webstore/bin/answer.py?hl=en&answer=186213 + +We should periodically look at +http://src.chromium.org/viewvc/chrome/trunk/src/chrome/app/generated_resources.grd?view=markup +to make sure that we're covering all messages. Search for +IDS_EXTENSION_PROMPT_WARNING +(e.g. IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY). +--> + +<p> +To use most chrome.* APIs and extension capabilities, +your extension must declare its intent in the +<a href="manifest.html">manifest</a>, +often in the "permissions" field. +Some of these declarations +result in a warning when +a user installs your extension. +</p> + +<p> +When you autoupdate your extension, +the user might see another warning +if the extension requests new permissions. +These new permissions might be new APIs that your extension uses, +or they might be new websites +that your extension needs access to. +</p> + + +<h2 id="examples"> Examples of permission warnings </h2> + +<p> +Here's a typical dialog +that a user might see when installing an extension: +</p> + +<img src="{{static}}/images/perms-hw1.png" + width="410" height="193" + alt="Permission warning: 'It can: Access your data on api.flickr.com'" + /> + +<p> +The warning about access to data on api.flickr.com +is caused by the following lines +in the extension's manifest: +</p> + +<pre> +"permissions": [ + <b>"http://api.flickr.com/"</b> +], +</pre> + +<p class="note"> +<b>Note:</b> +You don't see permission warnings when +you load an unpacked extension. +You get permission warnings only when you install an extension +from a <code>.crx</code> file. +</p> + +<p> +If you add a permission to the extension when you autoupdate it, +the user might see a new permission warning. +For example, +assume you add a new site and the "tabs" permission +to the previous example: +</p> + +<pre> +"permissions": [ + "http://api.flickr.com/", + <b>"http://*.flickr.com/", + "tabs"</b> +], +</pre> + +<p> +When the extension autoupdates, +the increased permissions +cause the extension to be disabled +until the user re-enables it. +Here's the warning the user sees: +</p> + +<img src="{{static}}/images/perms-hw2-disabled.png" + width="814" height="30" + alt="Warning text: 'The newest version of the extension Hello World requires more permissions, so it has been disabled. [Re-enable].'" + /> + +<p> +Clicking the Re-enable button +brings up the following warning: +</p> + +<img src="{{static}}/images/perms-hw2.png" + width="412" height="220" + alt="Permission warning: 'It can: Access your data on api.flickr.com and flickr.com; Read and modify your browsing history'" + /> + + +<h2 id="warnings"> Warnings and their triggers </h2> + +<p> +It can be surprising when adding a permission such as "tabs" +results in the seemingly unrelated warning +that the extension can access your browsing activity. +The reason for the warning is that +although the <code>chrome.tabs</code> API +might be used only to open new tabs, +it can also be used to see the URL that's associated +with every newly opened tab +(using their <a href="tabs.html#type-Tab">Tab</a> objects). +</p> + +<p class="note"> +<b>Note:</b> +As of Google Chrome 7, +you no longer need to specify the "tabs" permission +just to call <code>chrome.tabs.create()</code> +or <code>chrome.tabs.update()</code>. +</p> + +<p> +The following table lists the warning messages +that users can see, +along with the manifest entries +that trigger them. +</p> + +<p> +<table> +<tr> + <th>Warning message</th> <th>Manifest entry that causes it</th> <th>Notes</th> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_FULL_ACCESS --> + Access all data on your computer and the websites you visit + </td> + <td> + "plugins" + </td> + <td> + The "plugins" permission is required by + <a href="npapi.html">NPAPI plugins</a>. + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_BOOKMARKS --> + Read and modify your bookmarks + </td> + <td> + "bookmarks" permission + </td> + <td> + The "bookmarks" permission is required by the + <a href="bookmarks.html"><code>chrome.bookmarks</code></a> module. + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_BROWSING_HISTORY --> + Read and modify your browsing history + </td> + <td> + <!-- HasEffectiveBrowsingHistoryPermission --> + "history" permission + </td> + <td> + <p> + The "history" permission is required by + <a href="history.html"><code>chrome.history</code></a>. + </p> + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_TABS --> + Access your tabs and browsing activity + </td> + <td> + <!-- HasEffectiveBrowsingHistoryPermission --> + Any of the following: + <ul> + <li> "tabs" permission </li> + <li> "webNavigation" permission </li> + </ul> + </td> + <td> + <p> + The "tabs" permission is required by the + <a href="tabs.html"><code>chrome.tabs</code></a> and + <a href="windows.html"><code>chrome.windows</code></a> modules. + </p> + <p> + The "webNavigation" permission is required by the + <a href="webNavigation.html"><code>chrome.webNavigation</code></a> module. + </p> + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_CONTENT_SETTINGS --> + Manipulate settings that specify whether websites can use features such as cookies, JavaScript, and plug-ins + </td> + <td> + <!-- HasEffectiveBrowsingHistoryPermission --> + "contentSettings" permission + </td> + <td> + <p> + The "contentSettings" permission is required by + <a href="contentSettings.html"><code>chrome.contentSettings</code></a>. + </p> + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_ALL_HOSTS --> + Access your data on all websites + </td> + <td> + <!-- HasEffectiveAccessToAllHosts() --> + Any of the following: + <ul> + <li> "debugger" permission </li> + <li> "proxy" permission </li> + <li> A match pattern in the "permissions" field + that matches all hosts </li> + <li> A "content_scripts" field with a "matches" entry + that matches all hosts </li> + <li> "devtools_page" </li> + </ul> + </td> + <td> + <p> + The "debugger" permission is required by the experimental + <a href="experimental.debugger.html">debugger</a> module. + </p> + + <p> + The "proxy" permission is required by the + <a href="proxy.html"><code>chrome.proxy</code></a> module. + </p> + + <p> + Any of the following URLs match all hosts: + </p> + <ul> + <li> <code>http://*/*</code> </li> + <li> <code>https://*/*</code> </li> + <li> <code>*://*/*</code> </li> + <li> <code><all_urls></code> </li> + </ul> + </td> +</tr> +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_?_HOST --> + <!-- IDS_EXTENSION_PROMPT_WARNING_4_OR_MORE_HOSTS --> + Access your data on <em>{list of websites}</em> + </td> + <td> + A match pattern in the "permissions" field + that specifies one or more hosts, + but not all hosts + </td> + <td> + <p> + Up to 3 sites are listed by name. + Subdomains aren't treated specially. + For example, <code>a.com</code> and <code>b.a.com</code> + are listed as different sites. + </p> + + <p> + On autoupdate, + the user sees a permission warning + if the extension adds or changes sites. + For example, going from <code>a.com,b.com</code> + to <code>a.com,b.com,c.com</code> + triggers a warning. + Going from <code>b.a.com</code> + to <code>a.com</code>, + or vice versa, + also triggers a warning. + </p> + </td> +</tr> +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_ALL_PAGES_CONTENT --> + Access the content of pages you visit + </td> + <td> + "pageCapture" permission + </td> + <td> + The "pageCapture" permission is required by the + <a href="pageCapture.html"><code>chrome.pageCapture</code></a> module. + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_MANAGEMENT --> + Manage your apps, extensions, and themes + </td> + <td> + "management" permission + </td> + <td> + The "management" permission is required by the + <a href="management.html"><code>chrome.management</code></a> module. + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_GEOLOCATION --> + Detect your physical location + </td> + <td> + "geolocation" permission + </td> + <td> + Allows the extension to use the proposed HTML5 + <a href="http://dev.w3.org/geo/api/spec-source.html">geolocation API</a> + without prompting the user for permission. + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_CLIPBOARD--> + Access data you copy and paste + </td> + <td> + "clipboardRead" permission + </td> + <td> + Allows the extension to use the following editing commands with + <code>document.execCommand()</code>: + <ul> + <li> <code>"copy"</code> </li> + <li> <code>"cut"</code> </li> + </ul> + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_PRIVACY--> + Manipulate privacy-related settings + </td> + <td> + "privacy" permission + </td> + <td> + The "privacy" permission is required by the + <a href="privacy.html"><code>chrome.privacy</code></a> module. + </td> +</tr> + +<tr> + <td style="font-weight:bold"> + <!-- IDS_EXTENSION_PROMPT_WARNING_TTS_ENGINE--> + Access all text spoken using synthesized speech + </td> + <td> + "ttsEngine" permission + </td> + <td> + The "ttsEngine" permission is required by the + <a href="ttsEngine.html"><code>chrome.ttsEngine</code></a> module. + </td> +</tr> +</table> +</p> + + +<h2 id="nowarning"> Permissions that don't cause warnings </h2> + +<p> +The following permissions don't result in a warning: +</p> + +<ul> + <li>"browsingData"</li> + <li>"chrome://favicon/"</li> + <li>"clipboardWrite"</li> + <li>"contextMenus"</li> + <li>"cookies"</li> + <li>"experimental"</li> + <li>"idle"</li> + <li>"notifications"</li> + <li>"storage"</li> + <li>"unlimitedStorage"</li> + <li>"webRequest"</li> + <li>"webRequestBlocking"</li> +</ul> + +<h2 id="test"> Testing permission warnings </h2> + +<p> +If you'd like to see exactly which warnings your users will get, +<a href="packaging.html">package your extension</a> +into a <code>.crx</code> file, +and install it. +</p> + +<p> +To see the warnings users will get when your extension is autoupdated, +you can go to a little more trouble +and set up an autoupdate server. +To do this, first create an update manifest +and point to it from your extension, +using the "update_url" key +(see <a href="autoupdate.html">Autoupdating</a>). +Next, <a href="packaging.html">package the extension</a> +into a new <code>.crx</code> file, +and install the app from this <code>.crx</code> file. +Now, change the extension's manifest to contain the new permissions, +and <a href="packaging.html#update">repackage the extension</a>. +Finally, update the extension +(and all other extensions that have outstanding updates) +by clicking the <b>chrome://extensions</b> page's +<b>Update extensions now</b> button. +</p> + +<h2 id="api">API</h2> + +<p> +You can get a list of permission warnings for any manifest with +<a href="management.html#method-getPermissionWarnings">chrome.management.getPermissionWarnings()</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/publish_app.html b/chrome/common/extensions/docs/templates/articles/publish_app.html new file mode 100644 index 0000000..4ed8f86 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/publish_app.html @@ -0,0 +1,44 @@ +<h1>Publish</h1> +<!-- --> + +<p> +Packaged apps are still evolving. +We're giving you an early look at how to build them, +but it's a developer preview; +they aren't ready yet for building production applications. +</p> + +<p>This means that you can't just yet publish your packaged apps +in the Chrome Web Store — but you will be able to do so very soon.</p> + +<p>What you can do (as described throughout this guide), +is load your unpackaged app to the apps and extensions management page +and try out your app from a new tab in the Chrome browser.</p> + +<p>In case you haven't tried it yet, +here's how to load your app:</p> + +<ol> + <li style="margin-top:0" /> + Bring up the apps and extensions management page + by clicking the wrench icon + <img src="{{static}}/images/toolsmenu.gif" width="29" height="29" alt="" + style="margin-top:0" /> + and choosing <b>Tools > Extensions</b>. + </li> + <li> + Make sure the <b>Developer mode</b> + checkbox has been selected. + </li> + <li> + Click the <b>Load unpacked extension</b> button. + A file dialog appears. + </li> + <li> + In the file dialog, + navigate to your extension's folder + and click <b>OK</b>. + </li> +</ol> + +<p class="backtotop"><a href="#top">Back to top</a></p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/sandboxingEval.html b/chrome/common/extensions/docs/templates/articles/sandboxingEval.html new file mode 100644 index 0000000..84c17d4 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/sandboxingEval.html @@ -0,0 +1,198 @@ +<h1>Using eval in Chrome Extensions. Safely.</h1> + + +<p> + Chrome's extension system enforces a fairly strict default + <a href='contentSecurityPolicy.html'> + <strong>Content Security Policy (CSP)</strong> + </a>. The policy restrictions are straightforward: script must be moved + out-of-line into separate JavaScript files, inline event handlers must be + converted to use <code>addEventListener</code>, and <code>eval()</code> is + disabled. Chrome Apps have an + <a href='http://developer.chrome.com/trunk/apps/app_csp.html'>even more strict + policy</a>, and we're quite happy with the security properties these policies + provide. +</p> + +<p> + We recognize, however, that a variety of libraries use <code>eval()</code> and + <code>eval</code>-like constructs such as <code>new Function()</code> for + performance optimization and ease of expression. Templating libraries are + especially prone to this style of implementation. While some (like + <a href='http://angularjs.org/'>Angular.js</a>) support CSP out of the box, + many popular frameworks haven't yet updated to a mechanism that is compatible + with extensions' <code>eval</code>-less world. Removing support for that + functionality has therefore proven <a href='http://crbug.com/107538'>more + problematic than expected</a> for developers. +</p> + +<p> + This document introduces sandboxing as a safe mechanism to include these + libraries in your projects without compromising on security. For brevity, + we'll be using the term <em>extensions</em> throughout, but the concept + applies equally to applications. +</p> + +<h2>Why sandbox?</h2> + +<p> + <code>eval</code> is dangerous inside an extension because the code it + executes has access to everything in the extension's high-permission + environment. A slew of powerful <code>chrome.*</code> APIs are available that + could severely impact a user's security and privacy; simple data exfiltration + is the least of our worries. The solution on offer is a sandbox in which + <code>eval</code> can execute code without access either to the extension's + data or the extension's high-value APIs. No data, no APIs, no problem. +</p> + +<p> + We accomplish this by listing specific HTML files inside the extension package + as being sandboxed. Whenever a sandboxed page is loaded, it will be moved to a + <a href='http://www.whatwg.org/specs/web-apps/current-work/multipage/origin-0.html#sandboxed-origin-browsing-context-flag'>unique origin</a>, + and will be denied access to <code>chrome.*</code> APIs. If we load this + sandboxed page into our extension via an <code>iframe</code>, we can pass it + messages, let it act upon those messages in some way, and wait for it to pass + us back a result. This simple messaging mechanism gives us everything we need + to safely include <code>eval</code>-driven code in our extension's workflow. +</p> + +<h2>Creating and using a sandbox.</h2> + +<p> + If you'd like to dive straight into code, please grab the + <a href='http://code.google.com/chrome/extensions/samples.html#3c6dfba67f6a7480d931b5a4a646c151ad1a049b'>sandboxing + sample extension and take off</a>. It's a working example of a tiny messaging + API built on top of the <a href='http://handlebarsjs.com'>Handlebars</a> + templating library, and it should give you everything you need to get going. + For those of you who'd like a little more explanation, let's walk through that + sample together here. +</p> + +<h3>List files in manifest</h3> + +<p> + Each file that ought to be run inside a sandbox must be listed in the + extension manifest by adding a <code>sandbox</code> property. This is a + critical step, and it's easy to forget, so please double check that your + sandboxed file is listed in the manifest. In this sample, we're sandboxing the + file cleverly named "sandbox.html". The manifest entry looks like this: +</p> + +<pre>{ + ..., + "sandbox": { + "pages": ["sandbox.html"] + }, + ... +}</pre> + +<h3>Load the sandboxed file</h3> + +<p> + In order to do something interesting with the sandboxed file, we need to load + it in a context where it can be addressed by the extension's code. Here, + <a href='http://code.google.com/chrome/extensions/examples/howto/sandbox/sandbox.html'>sandbox.html</a> + has been loaded into the extension's <a href='http://code.google.com/chrome/extensions/dev/event_pages.html'>Event + Page</a> (<a href='http://code.google.com/chrome/extensions/examples/howto/sandbox/eventpage.html'>eventpage.html</a>) + via an <code>iframe</code>. <a href='http://code.google.com/chrome/extensions/examples/howto/sandbox/eventpage.js'>eventpage.js</a> + contains code that sends a message into the sandbox whenever the browser + action is clicked by finding the <code>iframe</code> on the page, and + executing the <code>postMessage</code> method on its + <code>contentWindow</code>. The message is an object containing two + properties: <code>context</code> and <code>command</code>. We'll dive into + both in a moment. +</p> + +<pre>chrome.browserAction.onClicked.addListener(function() { + var iframe = document.getElementById('theFrame'); + var message = { + command: 'render', + context: {thing: 'world'} + }; + iframe.contentWindow.postMessage(message, '*'); +});</pre> + +<p class="note"> + For general information about the <code>postMessage</code> API, take a look at + the <a href="https://developer.mozilla.org/en/DOM/window.postMessage"> + <code>postMessage</code> documentation on MDN + </a>. It's quite complete and worth reading. In particular, note that data can + only be passed back and forth if it's serializable. Functions, for instance, + are not. +</p> + +<h3>Do something dangerous</h3> + +<p> + When <code>sandbox.html</code> is loaded, it loads the Handlebars library, and + creates and compiles an inline template in the way Handlebars suggests: +</p> + +<pre><script src="handlebars-1.0.0.beta.6.js"></script> + <script id="hello-world-template" type="text/x-handlebars-template"> + <div class="entry"> + <h1>Hello, {{thing}}!</h1> + </div> + </script> + <script> + var templates = []; + var source = document.getElementById('hello-world-template').innerHTML; + templates['hello'] = Handlebars.compile(source); + </script></pre> + +<p> + This doesn't fail! Even though <code>Handlebars.compile</code> ends up using + <code>new Function</code>, things work exactly as expected, and we end up with + a compiled template in <code>templates[‘hello']</code>. +</p> + +<h3>Pass the result back</h3> + +<p> + We'll make this template available for use by setting up a message listener + that accepts commands from the Event Page. We'll use the <code>command</code> + passed in to determine what ought to be done (you could imagine doing more + than simply rendering; perhaps creating templates? Perhaps managing them in + some way?), and the <code>context</code> will be passed into the template + directly for rendering. The rendered HTML will be passed back to the Event + Page so the extension can do something useful with it later on: +</p> + +<pre>window.addEventListener('message', function(event) { + var command = event.data.command; + var name = event.data.name || 'hello'; + switch(command) { + case 'render': + event.source.postMessage({ + name: name, + html: templates[name](event.data.context) + }, event.origin); + break; + + // case 'somethingElse': + // ... + } +});</pre> + +<p> + Back in the Event Page, we'll receive this message, and do something + interesting with the <code>html</code> data we've been passed. In this case, + we'll just echo it out via a <a href='http://code.google.com/chrome/extensions/notifications.html'>Desktop + Notification</a>, but it's entirely possible to use this HTML safely as part + of the extension's UI. Inserting it via <code>innerHTML</code> doesn't pose a + significant security risk, as even a complete compromise of the sandboxed code + through some clever attack would be unable to inject dangerous script or + plugin content into the high-permission extension context. +</p> + +<p> + This mechanism makes templating straightforward, but it of course isn't + limited to templating. Any code that doesn't work out of the box under a + strict Content Security Policy can be sandboxed; in fact, it's often useful + to sandbox components of your extensions that <em>would</em> run correctly in + order to restrict each piece of your program to the smallest set of privileges + necessary for it to properly execute. The + <a href="http://www.youtube.com/watch?v=GBxv8SaX0gg">Writing Secure Web Apps + and Chrome Extensions</a> presentation from Google I/O 2012 gives some good + examples of these technique in action, and is worth 56 minutes of your time. +</p> diff --git a/chrome/common/extensions/docs/templates/articles/themes.html b/chrome/common/extensions/docs/templates/articles/themes.html new file mode 100644 index 0000000..d496ba7 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/themes.html @@ -0,0 +1,147 @@ +<h1 class="page_title">Themes</h1><p> +A <em>theme</em> is a special kind of extension +that changes the way the browser looks. +Themes are <a href="packaging.html">packaged</a> like regular extensions, +but they don't contain JavaScript or HTML code. +</p> + +<p> +You can find and try a bunch of themes at the +<a href="https://chrome.google.com/webstore/category/themes">Chrome Web Store</a>. +</p> + +<img src="{{static}}/images/themes-1.gif" + width="100" height="80" alt="grassy theme" /> + +<img src="{{static}}/images/themes-2.gif" + width="100" height="80" alt="dark theme" /> + +<img src="{{static}}/images/themes-3.gif" + width="100" height="80" alt="foggy theme" /> + +<h2 id="manifest"> Manifest </h2> +<p> +Here is an example +<a href="manifest.html"><code>manifest.json</code></a> +file for a theme: +</p> + + + +<pre> +{ + "version": "2.6", + "name": "camo theme", +<b> "theme": { + "<a href="#images">images</a>" : { + "theme_frame" : "images/theme_frame_camo.png", + "theme_frame_overlay" : "images/theme_frame_stripe.png", + "theme_toolbar" : "images/theme_toolbar_camo.png", + "theme_ntp_background" : "images/theme_ntp_background_norepeat.png", + "theme_ntp_attribution" : "images/attribution.png" + }, + "<a href="#colors">colors</a>" : { + "frame" : [71, 105, 91], + "toolbar" : [207, 221, 192], + "ntp_text" : [20, 40, 0], + "ntp_link" : [36, 70, 0], + "ntp_section" : [207, 221, 192], + "button_background" : [255, 255, 255] + }, + "<a href="#tints">tints</a>" : { + "buttons" : [0.33, 0.5, 0.47] + }, + "<a href="#properties">properties</a>" : { + "ntp_background_alignment" : "bottom" + } + }</b> +} +</pre> + +<h3 id="colors">colors</h3> + +<p> +Colors are in RGB format. +To find the strings you can use within the "colors" field, +look for kColor* strings in +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/theme_service.cc"><code>theme_service.cc</code></a>. +</p> + +<h3 id="images">images</h3> + +<p> +Image resources use paths relative to the root of the extension. +You can override any of the images that are specified by +<code>kThemeableImages</code> in +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/theme_service.cc"><code>theme_service.cc</code></a>. +Just remove the "IDR_" +and convert the remaining characters to lowercase. +For example, <code>IDR_THEME_NTP_BACKGROUND</code> +(which <code>kThemeableImages</code> uses +to specify the background of the new tab pane) +corresponds to "theme_ntp_background". +</p> + +<h3 id="properties">properties</h3> + +<p> +This field lets you specify +properties such as background alignment, +background repeat, +and an alternate logo. +To see the properties and the values they can have, see +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/theme_service.cc"><code>theme_service.cc</code></a>. + +</p> + +<h3 id="tints">tints</h3> + +<p> +You can specify tints to be applied to parts of the UI +such as buttons, the frame, and the background tab. +Google Chrome supports tints, not images, +because images don't work across platforms +and are brittle in the case of adding new buttons. +To find the strings you can use within the "tints" field, +look for kTint* strings in +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/themes/theme_service.cc"><code>theme_service.cc</code></a>. +</p> + +<p> +Tints are in Hue-Saturation-Lightness (HSL) format, +using floating-point numbers in the range 0 - 1.0: +</p> + +<ul> + <li> + <b>Hue</b> is an absolute value, with 0 and 1 being red. + </li> + <li> + <b>Saturation</b> is relative to the currently provided image. + 0.5 is <em>no change</em>, + 0 is <em>totally desaturated</em>, + and 1 is <em>full saturation</em>. + </li> + <li> + <b>Lightness</b> is also relative, + with 0.5 being <em>no change</em>, + 0 as <em>all pixels black</em>, + and 1 as <em>all pixels white</em>. + </li> +</ul> + +<p> +You can alternatively use <code>-1.0</code> for any of the HSL values +to specify <em>no change</em>. +</p> + + +<h2 id="moredoc"> Additional documentation </h2> + +<p> +Community-written documentation to help you write themes is here: +</p> + +<blockquote> +<a href="http://code.google.com/p/chromium/wiki/ThemeCreationGuide">http://code.google.com/p/chromium/wiki/ThemeCreationGuide</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/tut_analytics.html b/chrome/common/extensions/docs/templates/articles/tut_analytics.html new file mode 100644 index 0000000..ff0adca --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/tut_analytics.html @@ -0,0 +1,214 @@ +<h1>Tutorial: Google Analytics</h1> + + +<p>This tutorial demonstrates using Google Analytics to track the usage of your +extension.</p> + +<h2 id="toc-requirements">Requirements</h2> +<p> + This tutorial expects that you have some familiarity writing extensions for + Google Chrome. If you need information on how to write an extension, please + read the <a href="gettingstarted.html">Getting Started tutorial</a>. +</p> + +<p> + You will also need a <a href="http://www.google.com/analytics">Google + Analytics account</a> set up to track your extension. Note that when setting + up the account, you can use any value in the Website's URL field, as your + extension will not have an URL of its own. +</p> + +<p style="text-align: center"> + <img src="{{static}}/images/tut_analytics/screenshot01.png" + style="width:400px;height:82px;" + alt="The analytics setup with info for a chrome extension filled out." /> +</p> + +<h2 id="toc-installing">Installing the tracking code</h2> + +<p> + The standard Google Analytics tracking code snippet fetches a file named + <code>ga.js</code> from an SSL protected URL if the current page + was loaded using the <code>https://</code> protocol. <strong>Chrome + extensions and applications may <em>only</em> use the SSL-protected version of + <code>ga.js</code></strong>. Loading <code>ga.js</code> over insecure HTTP is + disallowed by Chrome's default <a href="contentSecurityPolicy.html">Content + Security Policy</a>. This, plus the fact that Chrome extensions are hosted + under the <code>chrome-extension://</code> schema, requires a slight + modification to the usual tracking snippet to pull <code>ga.js</code> directly + from <code>https://ssl.google-analytics.com/ga.js</code> instead of the + default location. +</p> + +<p> + Below is a modified snippet for the + <a href="http://code.google.com/apis/analytics/docs/tracking/asyncTracking.html">asynchronous + tracking API</a> (the modified line is bolded): +</p> + +<pre> +(function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + <strong>ga.src = 'https://ssl.google-analytics.com/ga.js';</strong> + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); +})(); +</pre> + +<p> + You'll also need to ensure that your extension has access to load the resource + by relaxing the default content security policy. The policy definition in your + <a href="manifest.html"><code>manifest.json</code></a> might look like: +</p> + +<pre>{ + ..., + "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", + ... +}</pre> + +<p> + Here is a popup page (<code>popup.html</code>) which loads the asynchronous + tracking code via an external JavaScript file (<code>popup.js</code>) and + tracks a single page view: +</p> + +<pre>popup.js: +========= + +var _gaq = _gaq || []; +_gaq.push(['_setAccount', 'UA-XXXXXXXX-X']); +_gaq.push(['_trackPageview']); + +(function() { + var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; + ga.src = 'https://ssl.google-analytics.com/ga.js'; + var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); +})(); + +popup.html: +=========== +<!DOCTYPE html> +<html> + <head> + ... + <script src="popup.js"></script> + </head> + <body> + ... + </body> +</html> +</pre> + +<p> + Keep in mind that the string <code>UA-XXXXXXXX-X</code> should be replaced + with your own Google Analytics account number. +</p> + +<h2 id="toc-tracking-pageviews">Tracking page views</h2> + +<p> + The <code>_gaq.push(['_trackPageview']);</code> code will track a single + page view. This code may be used on any page in your extension. When + placed on a background page, it will register a view once per browser + session. When placed on a popup, it will register a view once every time + the popup is opened. +</p> + +<p> + By looking at the page view data for each page in your extension, you can + get an idea of how many times your users interact with your extension per + browser session: +</p> + +<p style="text-align: center"> + <img src="{{static}}/images/tut_analytics/screenshot02.png" + style="width:300px;height:119px;" + alt="Analytics view of the top content for a site." /> +</p> + +<h2 id="toc-debugging">Monitoring analytics requests</h2> + +<p> + To ensure that tracking data from your extension is being sent to Google + Analytics, you can inspect the pages of your extension in the + Developer Tools window (see the + <a href="tut_debugging.html">debugging tutorial</a> for more information). + As the following figure shows, you should see requests for a file named + <strong>__utm.gif</strong> if everything is set up correctly. +</p> + +<p style="text-align: center"> + <img src="{{static}}/images/tut_analytics/screenshot04.png" + style="width:683px;height:418px;" + alt="Developer Tools window showing the __utm.gif request" /> +</p> + +<h2 id="toc-tracking-events">Tracking events</h2> + +<p> + By configuring event tracking, you can determine which parts of your + extension your users interact with the most. For example, if you have + three buttons users may click: +</p> + +<pre> + <button id='button1'>Button 1</button> + <button id='button2'>Button 2</button> + <button id='button3'>Button 3</button> +</pre> + +<p> + Write a function that sends click events to Google Analytics: +</p> + +<pre> + function trackButton(e) { + _gaq.push(['_trackEvent', e.target.id, 'clicked']); + }; +</pre> + +<p> + And use it as an event handler for each button's click: +</p> + +<pre> + var buttons = document.querySelectorAll('button'); + for (var i = 0; i < buttons.length; i++) { + buttons[i].addEventListener('click', trackButtonClick); + } +</pre> + +<p> + The Google Analytics event tracking overview page will give you metrics + regarding how many times each individual button is clicked: +</p> + +<p style="text-align: center"> + <img src="{{static}}/images/tut_analytics/screenshot03.png" + style="width:300px;height:482px;" + alt="Analytics view of the event tracking data for a site." /> +</p> + +<p> + By using this approach, you can see which parts of your extension are + under-or-overutilized. This information can help guide decisions about UI + redesigns or additional functionality to implement. +</p> + +<p> + For more information about using event tracking, see the + Google Analytics + <a href="https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide">developer + documentation</a>. +</p> + +<h2 id="toc-samplecode">Sample code</h2> + +<p> + A sample extension that uses these techniques is + available in the Chromium source tree: +</p> + +<blockquote> + <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/tutorials/analytics/">.../examples/tutorials/analytics/</a> +</blockquote>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/tut_debugging.html b/chrome/common/extensions/docs/templates/articles/tut_debugging.html new file mode 100644 index 0000000..2bac501 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/tut_debugging.html @@ -0,0 +1,262 @@ +<h1>Tutorial: Debugging</h1> + + +<p> +This tutorial introduces you to using +Google Chrome's built-in Developer Tools +to interactively debug an extension. +</p> + + +<h2 id="extension-info"> View extension information </h2> + +<p> +To follow this tutorial, you need +the Hello World extension that was featured in +<a href="getstarted.html">Getting Started</a>. +In this section, +you'll load the extension +and take a look at its information +in the Extensions page. +</p> + +<ol> + <li> + <p> + Load the Hello World extension if it isn't already running. + If the extension is running, + you'll see the Hello World icon + <img src="../examples/tutorials/getstarted/icon.png" + width="19" height="19" alt="" + style="margin:0" /> + to the right of + your browser's address bar. + </p> + + <p> + If the Hello World extension isn't already running, + find the extension files and load them. + If you don't have a handy copy of the files, + extract them from this + <a href="../examples/tutorials/getstarted.zip">ZIP file</a>. + See Getting Started if you need + <a href="getstarted.html#load-ext">instructions + for loading the extension</a>. + </p> + </li> + + <li> + Go to the Extensions page + (<b>chrome://extensions</b>), + and make sure the page is in Developer mode. + </li> + + <li> + Look at the Hello World extension's information on that page. + You can see details such as the extension's + name, description, and ID. + </li> +</ol> + +<h2 id="inspect-popup"> Inspect the popup </h2> + +<p> +As long as your browser is in Developer mode, it's easy to inspect popups. +</p> + +<ol> + <li> + Go to the Extensions page (<b>chrome://extensions</b>), and make sure Developer + mode is still enabled. The Extensions page doesn't need to be open + for the following to work. The browser remembers the setting, + even when the page isn't shown. + </li> + <li> + Right-click the Hello World icon + <img src="../examples/tutorials/getstarted/icon.png" + width="19" height="19" alt="" + style="margin:0" /> + and choose the <b>Inspect popup</b> menu item. The popup appears, + and a Developer Tools window like the following should display the code + for <b>popup.html</b>. + + <p> + <img src="{{static}}/images/devtools-1.gif" alt="" + width="500" height="294" /> + </p> + The popup remains open as long as the Developer Tools window does. + </li> + <li> + If the <strong>Scripts</strong> button isn't already selected, + click it. + + </li> + <li> + Click the console button + <img src="{{static}}/images/console-button.gif" + style="margin:0; padding:0" align="absmiddle" + width="26" height="22" alt="" />(second + from left, + at the bottom of the Developer Tools window) + so that you can see both the code and the console. + </li> +</ol> + +<h2 id="debug"> Use the debugger </h2> + +<p> +In this section, +you'll follow the execution of the popup page +as it adds images to itself. +</p> + +<ol> + <li> + Set a breakpoint inside the image-adding loop + by searching for the string <b>img.src</b> + and clicking the number of the line where it occurs + (for example, <strong>37</strong>): + <p> + <img src="{{static}}/images/devtools-2.gif" alt="" + width="500" height="294" /> + </p> + </li> + + <li> + Make sure you can see the <b>popup.html</b> tab. + It should show 20 "hello world" images. + </li> + + <li> + At the console prompt, reload the popup page + by entering <b>location.reload(true)</b>: + +<pre> +> <b>location.reload(true)</b> +</pre> + + <p> + The popup page goes blank as it begins to reload, + and its execution stops at line 37. + </p> + </li> + + <li> + In the upper right part of the tools window, + you should see the local scope variables. + This section shows the current values of all variables in the current scope. + For example, in the following screenshot + the value of <code>i</code> is 0, and + <code>photos</code> is a node list + that contains at least a few elements. + (In fact, it contains 20 elements at indexes 0 through 19, + each one representing a photo.) + + <p> + <img src="{{static}}/images/devtools-localvars.gif" alt="" + width="225" height="215" /> + </p> + </li> + + <li> + Click the play/pause button + <img src="{{static}}/images/play-button.gif" + style="margin:0; padding:0" align="absmiddle" + width="22" height="20" alt="" />(near + the top right of the Developer Tools window) + to go through the image-processing loop a single time. + Each time you click that button, + the value of <code>i</code> increments and + another icon appears in the popup page. + For example, when <code>i</code> is 10, + the popup page looks something like this: + </li> + + <p> + <img src="{{static}}/images/devtools-3.gif" + width="500" height="245" + alt="the popup page with 10 images" /> + </p> + + <li> + Use the buttons next to the play/pause button + to step over, into, and out of function calls. + To let the page finish loading, + click line <b>37</b> to disable the breakpoint, + and then press play/pause + <img src="{{static}}/images/play-button.gif" + style="margin:0; padding:0" align="absmiddle" + width="22" height="20" alt="" />to + continue execution. + </li> + +</ol> + + +<h2 id="summary">Summary</h2> + +<p> +This tutorial demonstrated some techniques you can use +to debug your extensions: +</p> + +<ul> + <li> + Find your extension's ID and links to its pages in + the <b>Extensions</b> page + (<b>chrome://extensions</b>). + </li> + <li> + View hard-to-reach pages + (and any other file in your extension) using + <b>chrome-extension://</b><em>extensionId</em><b>/</b><em>filename</em>. + </li> + <li> + Use Developer Tools to inspect + and step through a page's JavaScript code. + </li> + <li> + Reload the currently inspected page from the console + using <b>location.reload(true)</b>. + </li> +</ul> + + +<h2 id="next">Now what?</h2> + +<p> +Now that you've been introduced to debugging, +here are suggestions for what to do next: +</p> + +<ul> + <li> + Watch the extensions video + <a href="http://www.youtube.com/watch?v=IP0nMv_NI1s&feature=PlayList&p=CA101D6A85FE9D4B&index=5">Developing and Debugging</a>. + </li> + <li> + Try installing and inspecting other extensions, + such as the + <a href="samples.html">samples</a>. + </li> + <li> + Try using widely available debugging APIs such as + <code>console.log()</code> and <code>console.error()</code> + in your extension's JavaScript code. + Example: <code>console.log("Hello, world!")</code> + </li> + <li> + Follow the <a href="http://www.chromium.org/devtools/google-chrome-developer-tools-tutorial">Developer Tools tutorial</a>, + explore the + <a href="http://www.chromium.org/devtools">Developer Tools site</a>, + and watch some video tutorials. + </li> +</ul> + + + +<p> +For more ideas, +see the <a href="getstarted.html#summary">Now what?</a> section +of Getting Started. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/tut_migration_to_manifest_v2.html b/chrome/common/extensions/docs/templates/articles/tut_migration_to_manifest_v2.html new file mode 100644 index 0000000..9bacc2f --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/tut_migration_to_manifest_v2.html @@ -0,0 +1,358 @@ +<h1>Tutorial: Migrate to Manifest V2</h1> + +<p> +Manifest version 1 was deprecated in Chrome 18, +and support will be phased out according to the +<a href="manifestVersion.html">manifest version 1 support schedule</a>. +The changes from version 1 to version 2 +fall under two broad categories: +API changes and Security changes. +</p> + +<p> +This document provides checklists for migrating your Chrome extensions +from manifest version 1 to version 2, +followed by more detailed summaries of what these changes mean and why they were made. +</p> + +<h2 id="api-checklist">API changes checklist</h2> + +<ul> + <li>Are you using the <code>browser_actions</code> property + or the <code>chrome.browserActions</code> API?</li> + <ul> + <li>Replace <code>browser_actions</code> + with the singular <code>browser_action</code> property.</li> + <li>Replace <code>chrome.browserActions</code> with + <code>chrome.browserAction</code>.</li> + <li>Replace the <code>icons</code> property with <code>default_icon</code>.</li> + <li>Replace the <code>name</code> property with <code>default_title</code>.</li> + <li>Replace the <code>popup</code> property with + <code>default_popup</code> (and it now must be a string).</li> + </ul> + <li>Are you using the <code>page_actions</code> property + or the <code>chrome.pageActions</code> API?</li> + <ul> + <li>Replace <code>page_actions</code> with <code>page_action</code>.</li> + <li>Replace <code>chrome.pageActions</code> with <code>chrome.pageAction</code>.</li> + <li>Replace the <code>icons</code> property with <code>default_icon</code>.</li> + <li>Replace the <code>name</code> property with <code>default_title</code>.</li> + <li>Replace the <code>popup</code> property with + <code>default_popup </code>(and it now must be a string).</li> + </ul> + <li>Are you using the <code>chrome.self</code> property?</li> + <ul> + <li>Replace with <code>chrome.extension</code>.</li> + </ul> + <li>Are you using the <code>Port.tab</code> property?</li> + <ul> + <li>Replace with <code>Port.sender</code>.</li> + </ul> + <li>Are you using the <code>chrome.extension.getTabContentses()</code> + or the <code>chrome.extension.getExtensionTabs()</code> APIs?</li> + <ul> + <li>Replace with <code>chrome.extension.getViews( { “type” : “tab” } )</code>.</li> + </ul> + <li>Does your extension use a background page?</li> + <ul> + <li>Replace the <code>background_page</code> property + with a <code>background</code> property.</li> + <li>Add a <code>scripts</code> or <code>page</code> + property that contains the code for the page.</li> + <li>Add a <code>persistent</code> property and set it + to <code>false</code> to convert your background page + to an <a href="event_pages.html">event page</a></li> + </ul> +</ul> + +<h2 id="security-checklist">Security changes checklist</h2> + +<ul> + <li>Are you using inline script blocks in HTML pages?</li> + <ul> + <li>Remove JS code contained within <script> tags + and place it within an external JS file.</li> + </ul> + <li>Are you using inline event handlers (like onclick, etc)?</li> + <ul> + <li>Remove them from the HTML code, + move them into an external JS file and + use <code>addEventListener()</code> instead.</li> + </ul> + <li>Does your extension inject content scripts into Web pages + that need to access resources (like images and scripts) + that are contained in the extension’s package?</li> + <ul> + <li>Define the <a href="manifest.html#web_accessible_resources">web_accessible_resources</a> + property and list the resources + (and optionally a separate Content Security Policy for those resources).</li> + </ul> + <li>Does your extension embed external Web pages?</li> + <ul> + <li>Define the <a href="manifest.html#sandbox">sandbox</a> property.</li> + </ul> + <li>Is your code or library using <code>eval()</code>, new <code>Function()</code>, + <code>innerHTML</code>, <code>setTimeout()</code>, or otherwise passing strings + of JS code that are dynamically evaluated?</li> + <ul> + <li>Use <code>JSON.parse()</code> + if you’re parsing JSON code into an object.</li> + <li>Use a CSP-friendly library, + for example, <a href="http://angularjs.org/">AngularJS</a>.</li> + <li>Create a sandbox entry in your manifest and + run the affected code in the sandbox, + using <code>postMessage()</code> to communicate + with the sandboxed page.</li> + </ul> + <li>Are you loading external code, + such as jQuery or Google Analytics?</li> + <ul> + <li>Consider downloading the library and + packaging it in your extension, + then loading it from the local package.</li> + <li>Whitelist the HTTPS domain that serves the resource + in the "content_security_policy” part of your manifest.</li> + </ul> +</ul> + +<h2 id="api-summary">Summary of API changes</h2> + +<p> +Manifest version 2 introduces a few changes +to the browser action and page action APIs, +and replaces a few old APIs with newer ones. +</p> + +<h3>Changes to browser actions</h3> + +<p> +The browser actions API introduces some naming changes:</p> + +<ul> + <li>The <code>browser_actions</code> and + <code>chrome.browserActions</code> properties have been replaced + with their singular counterparts <code>browser_action</code> + and <code>chrome.browserAction</code>.</li> + <li>Under the old <code>browser_actions</code> property, + there were <code>icons</code>, <code>name</code>, and + <code>popup</code> properties. + These have been replaced with:</li> + <ul> + <li><code>default_icon</code> for the browser action badge icon</li> + <li><code>default_name</code> for the text that appears in the tooltip when you hover over the badge</li> + <li><code>default_popup</code> for the HTML page that represents the UI + for the browser action (and this must now be a string, it cannot be an object)</li> + </ul> +</ul> + +<h3>Changes to page actions</h3> + +<p>Similar to the changes for browser actions, + the page actions API has also changed:</p> +<ul> + <li>The <code>page_actions</code> and <code>chrome.pageActions</code> properties + have been replaced with their singular counterparts + <code>page_action</code> and <code>chrome.pageAction</code>.</li> + <li>Under the old <code>page_actions</code> property, + there were <code>icons</code>, <code>name</code>, + and <code>popup</code> properties. + These have been replaced with:</li> + <ul> + <li><code>default_icon</code> for the page action badge icon</li> + <li><code>default_name</code> for the text + that appears in the tooltip when you hover over the badge</li> + <li><code>default_popup</code> for the HTML page + that represents the UI for the page action + (and this must now be a string, it cannot be an object)</li> + </ul> +</ul> + +<h3>Removed and changed APIs</h3> + +<p> +A few extension APIs have been removed and replaced with new counterparts: +</p> + +<ul> + <li>The <code>background_page</code> property has been replaced + by <a href="background_pages.html">background</a>.</li> + <li>The <code>chrome.self</code> property has been removed, + use <code>chrome.extension</code>.</li> + <li>The <code>Port.tab</code> property has been replaced + with <code>Port.sender</code>.</li> + <li>The <code>chrome.extension.getTabContentses()</code> and the + <code>chrome.extension.getExtensionTabs()</code> APIs have been replaced + by <code>chrome.extension.getViews( { “type” : “tab” } )</code>.</li> +</ul> + +<h2 id="security-summary">Summary of security changes</h2> + +<p> +There are a number of security-related changes +that accompany the move from manifest version 1 to version 2. +Many of these changes stem from Chrome’s adoption of +<a href="contentSecurityPolicy.html#H3-1">Content Security Policy</a>; +you should read more about this policy to understand its implications. +</p> + +<h3>Inline scripts and event handlers disallowed</h3> + +<p> +Due to the use of <a href="contentSecurityPolicy.html">Content Security Policy</a>, +you can no longer use <script> tags that are inline with the HTML content. +These must be moved to external JS files. +In addition, inline event handlers are also not supported. +For example, suppose you had the following code in your extension: +</p> + +<pre> +<html> +<head> + <script> + function myFunc() { ... } + </script> +</head> +</html> +</pre> + +<p> +This code would cause an error at runtime. +To fix this, move <script> tag contents to external files +and reference them with a <code>src=’path_to_file.js’</code> attribute. +</p> + +<p> +Similarly, inline event handlers, +which are a common occurrence and convenience feature +used by many Web developers, will not execute. +For example, consider common instances such as: +</p> + +<pre> +<body onload=”initialize()”> +<button onclick=”handleClick()” id=”button1”> +</pre> + +<p> +These will not work in manifest V2 extensions. +Remove the inline event handlers, +place them in your external JS file and use <code>addEventListener()</code> +to register event handlers for them instead. +For example, in your JS code, use: +</p> + +<pre> +window.addEventListener(“load”, initialize); +... +document.getElementById(“button1”).addEventListener(“click”,handleClick); +</pre> + +<p> +This is a much cleaner way of separating +your extension’s behavior from its user interface markup. +</p> + +<h3>Embedding content</h3> + +<p> +There are some scenarios where your extension might embed content +that can be used externally or come from an external source. +</p> + +<p> +<strong>Extension content in web pages:</strong><br> +If your extension embeds resources (like images, script, CSS styles, etc) +that are used in content scripts that are injected into web pages, +you need to use the +<a href="manifest.html#web_accessible_resources">web_accessible_resources</a> property +to whitelist these resources so that external Web pages can use them: +</p> + +<pre> +{ // manifest file +... + "<strong>web_accessible_resources</strong>": [ + "images/image1.png", + "script/myscript.js" + ], +... +} +</pre> + +<p> +<strong>Embedding external content:</strong><br> +The Content Security Policy only allows local script +and objects to loaded from your package, +which prevents external attackers from introducing unknown code to your extension. +However, there are times when you want to load externally served resources, +such as jQuery or Google Analytics code. +There are two ways to do this: +</p> + +<ol> + <li>Download the relevant library locally (like jQuery) + and package it with your extension.</li> + <li>You can relax the CSP in a limited way by whitelisting HTTPS origins + in the “content_security_policy” section of your manifest. + To include a library like Google Analytics, this is the approach to take: + <pre> + { // manifest file + ..., + "content_security_policy": "script-src 'self' + <strong>https://ssl.google-analytics.com</strong>; object-src 'self'", + ... + } + </pre></li> +</ol> + +<h3>Using dynamic script evaluation</h3> + +<p> +Perhaps one of the biggest changes in the new manifest v2 scheme is +that extensions can no longer use dynamic script evaluation techniques like +<code>eval()</code> or new <code>Function()</code>, +or pass strings of JS code to functions +that will cause an <code>eval()</code> to be used, +like <code>setTimeout()</code>. +In addition, certain commonly used JavaScript libraries, +such as Google Maps and certain templating libraries, +are known to use some of these techniques. +</p> + +<p> +Chrome provides a sandbox for pages to run in their own origin, +which are denied access to chrome.* APIs. +In order to use <code>eval()</code> +and the like under the new Content Security Policy: +</p> + +<ol> + <li>Create a sandbox entry in your manifest file.</li> + <li>In the sandbox entry, + list the pages you want to run in the sandbox.</li> + <li>Use message passing via <code>postMessage()</code> + to communicate with the sandboxed page.</li> +</ol> + +<p> +For more details on how to do this, +see the <a href="sandboxingEval.html">Sandboxing Eval</a> documentation. +</p> + +<h2 id="further-reading">Further reading</h2> + +<p> +The changes in manifest version 2 are designed to guide developers +toward building more secure and robustly-architected extensions and apps. +To see a complete list of changes from manifest version 1 to version 2, +see the <a href="manifestVersion.html">manifest file</a> documentation. +For more information about using sandboxing to isolate unsafe code, +read the <a href="sandboxingEval.html">sandboxing eval</a> article. +You can learn more about Content Security Policy +by visiting our extensions-related tutorial and a +<a href="http://www.html5rocks.com/en/tutorials/security/content-security-policy/">good introduction on HTML5Rocks</a>. +</p> + + + + diff --git a/chrome/common/extensions/docs/templates/articles/tut_oauth.html b/chrome/common/extensions/docs/templates/articles/tut_oauth.html new file mode 100644 index 0000000..594a8cb --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/tut_oauth.html @@ -0,0 +1,215 @@ +<h1>Tutorial: OAuth</h1> + + +<p> +<a href="http://oauth.net/">OAuth</a> is an open protocol that aims to standardize the way desktop and web applications access a user's private data. OAuth provides a mechanism for users to grant access to private data without sharing their private credentials (username/password). Many sites have started enabling APIs to use OAuth because of its security and standard set of libraries. +</p> +<p> +This tutorial will walk you through the necessary steps for creating a Google Chrome Extension that uses OAuth to access an API. It leverages a library that you can reuse in your extensions. +</p> +<p> +This tutorial uses the <a href="http://code.google.com/apis/documents/">Google Documents List Data API</a> as an example OAuth-enabled API endpoint. +</p> + +<h2 id="requirements">Requirements</h2> + +<p> +This tutorial expects that you have some experience writing extensions for Google Chrome and some familiarity with the <a href="http://code.google.com/apis/accounts/docs/OAuth.html">3-legged OAuth</a> flow. Although you don’t need a background in the <a href="http://code.google.com/apis/documents/">Google Documents List Data API</a> (or the other <a href="http://code.google.com/apis/gdata/">Google Data APIs</a> for that matter), having a understanding of the protocol may be helpful. +</p> + +<h2 id="getting-started">Getting started</h2> + +<p> +First, copy over the three library files from the Chromium source tree at <a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/">.../examples/extensions/oauth_contacts/</a>: +</p> +<ul> +<li><strong><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.html?revision=34725&content-type=text/plain">chrome_ex_oauth.html</a></strong> - interstitial page for the oauth_callback URL</li> +<li><strong><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauth.js?content-type=text/plain">chrome_ex_oauth.js</a></strong> - core OAuth library</li> +<li><strong><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/chrome_ex_oauthsimple.js?content-type=text/plain">chrome_ex_oauthsimple.js</a></strong> - helpful wrapper for chrome_ex_oauth.js</li> +</ul> + +<p>Place the three library files in the root of your extension directory (or wherever your JavaScript is stored). Then include both .js files in your background page in the following order:</p> + +<pre> +<script type="text/javascript" src="chrome_ex_oauthsimple.js"></script> +<script type="text/javascript" src="chrome_ex_oauth.js"></script> +</pre> + +<p>Your background page will manage the OAuth flow.</p> + +<h2 id="oauth-dance">The OAuth dance in an extension</h2> + +<p> +If you are familiar with the OAuth protocol, you'll recall that the OAuth dance consists of three steps: +</p> + +<ol> +<li>fetching an initial request token</li> +<li>having the user authorize the request token</li> +<li>fetching an access token</li> +</ol> + +<p>In the context of an extension, this flow gets a bit tricky. Namely, there is no established consumer key/secret between the service provider and the application. That is, there is no web application URL for the user to be redirected to after the approval process. +</p> + +<p> +Luckily, Google and a few other companies have been working on an <a href="http://code.google.com/apis/accounts/docs/OAuthForInstalledApps.html">OAuth for installed applications</a> solution that you can use from an extension environment. In the installed applications OAuth dance, the consumer key/secret are ‘anonymous’/’anonymous’ and you provide an <em>application name</em> for the user to grant access to (instead of an application URL). The end result is the same: your background page requests the initial token, opens a new tab to the approval page, and finally makes the asynchronous call for the access token. +</p> + +<h3 id="set-code">Setup code</h3> + +<p>To initialize the library, create a <code>ChromeExOAuth</code> object in the background page:</p> + +<pre> +var oauth = ChromeExOAuth.initBackgroundPage({ + 'request_url': <OAuth request URL>, + 'authorize_url': <OAuth authorize URL>, + 'access_url': <OAuth access token URL>, + 'consumer_key': <OAuth consumer key>, + 'consumer_secret': <OAuth consumer secret>, + 'scope': <scope of data access, not used by all OAuth providers>, + 'app_name': <application name, not used by all OAuth providers> +}); +</pre> + +<p>In the case of the Documents List API and Google’s OAuth endpoints, a possible initialization may be:</p> + +<pre> +var oauth = ChromeExOAuth.initBackgroundPage({ + 'request_url': 'https://www.google.com/accounts/OAuthGetRequestToken', + 'authorize_url': 'https://www.google.com/accounts/OAuthAuthorizeToken', + 'access_url': 'https://www.google.com/accounts/OAuthGetAccessToken', + 'consumer_key': 'anonymous', + 'consumer_secret': 'anonymous', + 'scope': 'https://docs.google.com/feeds/', + 'app_name': 'My Google Docs Extension' +}); +</pre> + +<p> +To use the OAuth library, +you must declare the "tabs" permision in the +<a href="http://code.google.com/chrome/extensions/manifest.html">extension manifest</a>. +You must also declare the sites you are using +including the request URL, the authorize URL, access URL, +and, if necessary, the scope URL. +For example: +</p> + +<pre> +"permissions": [ "tabs", "https://docs.google.com/feeds/*", + "https://www.google.com/accounts/OAuthGetRequestToken", + "https://www.google.com/accounts/OAuthAuthorizeToken", + "https://www.google.com/accounts/OAuthGetAccessToken" +] +</pre> + +<h3 id="request-token">Fetching and authorizing a request token</h3> + +<p> +Once you have your background page set up, call the <code>authorize()</code> function to begin the OAuth dance and redirect the user to the OAuth provider. The client library abstracts most of this process, so all you need to do is pass a callback to the <code>authorize()</code> function, and a new tab will open and redirect the user. +</p> + +<pre> +oauth.authorize(function() { + // ... Ready to fetch private data ... +}); +</pre> + +<p> +You don't need to provide any additional logic for storing the token and secret, as this library already stores these values in the browser’s <code>localStorage</code>. If the library already has an access token stored for the current scope, then no tab will be opened. In either case, the callback will be called. +</p> + +<h3 id="signed-requests">Sending signed API requests</h3> + +<p> +Once your specified callback is executed, call the <code>sendSignedRequest()</code> function to send signed requests to your API endpoint(s). <code>sendSignedRequest()</code> takes three arguments: a URI, a callback function, and an optional parameter object. The callback is passed two arguments: the response text and the <code>XMLHttpRequest</code> object that was used to make the request. +</p> + +<p>This example sends an HTTP <code>GET</code>:</p> + +<pre> +function callback(resp, xhr) { + // ... Process text response ... +}; + +function onAuthorized() { + var url = 'https://docs.google.com/feeds/default/private/full'; + var request = { + 'method': 'GET', + 'parameters': {'alt': 'json'} + }; + + // Send: GET https://docs.google.com/feeds/default/private/full?alt=json + oauth.sendSignedRequest(url, callback, request); +}; + +oauth.authorize(onAuthorized); +</pre> + +<p>A more complex example using an HTTP <code>POST</code> might look like this:</p> + +<pre> +function onAuthorized() { + var url = 'https://docs.google.com/feeds/default/private/full'; + var request = { + 'method': 'POST', + 'headers': { + 'GData-Version': '3.0', + 'Content-Type': 'application/atom+xml' + }, + 'parameters': { + 'alt': 'json' + }, + 'body': 'Data to send' + }; + + // Send: POST https://docs.google.com/feeds/default/private/full?alt=json + oauth.sendSignedRequest(url, callback, request); +}; +</pre> + +<p> +By default, the <code>sendSignedRequest()</code> function sends the <code>oauth_*</code> parameters in the URL (by calling <code>oauth.signURL()</code>). If you prefer to send the <code>oauth_*</code> parameters in the <code>Authorization</code> header (or need direct access to the generated header), use <code>getAuthorizationHeader()</code>. Its arguments are a URI, an HTTP method, and an optional object of URL query parameters as key/value pairs. +</p> + +<p>Here is the example above using <code>getAuthorizationHeader()</code> and an <code>XMLHttpRequest</code> object:</p> + +<pre> +function stringify(parameters) { + var params = []; + for(var p in parameters) { + params.push(encodeURIComponent(p) + '=' + + encodeURIComponent(parameters[p])); + } + return params.join('&'); +}; + +function onAuthorized() { + var method = 'POST'; + var url = 'https://docs.google.com/feeds/default/private/full'; + var params = {'alt': 'json'}; + + var xhr = new XMLHttpRequest(); + xhr.onreadystatechange = function(data) { + callback(xhr, data); + }; + xhr.open(method, url + '?' + stringify(params), true); + xhr.setRequestHeader('GData-Version', '3.0'); + xhr.setRequestHeader('Content-Type', 'application/atom+xml'); + xhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params)); + + xhr.send('Data to send'); +}; +</pre> + +<h2 id="sample-code">Sample code</h2> + +<p> +Sample extensions that use these techniques are available in the Chromium source tree: +</p> + +<ul> +<li><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/gdocs/">.../examples/extensions/gdocs/</a></li> +<li><a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/oauth_contacts/">.../examples/extensions/oauth_contacts/</a></li> +</ul> diff --git a/chrome/common/extensions/docs/templates/articles/tutorials.html b/chrome/common/extensions/docs/templates/articles/tutorials.html new file mode 100644 index 0000000..79fbf87 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/tutorials.html @@ -0,0 +1,29 @@ +<h1>Tutorials</h1> + +<p> +Follow these to get started +developing Google Chrome Extensions: +</p> + +<ul> + <li> <a href="getstarted.html">Getting Started</a> </li> + <li> <a href="tut_debugging.html">Debugging</a> </li> +</ul> + +<p> +The remaining tutorials cover +more specialized topics: +</p> + +<ul> + <li> <a href="tut_analytics.html">Google Analytics</a> - + Track the usage of your extension. + </li> + <li> <a href="tut_oauth.html">OAuth</a> - + Learn how your extension can use APIs + (such as <a href="http://code.google.com/apis/gdata/">Google Data APIs</a>) + that support OAuth. + This tutorial features an OAuth library + that you can reuse in your extension. + </li> +</ul>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/articles/whats_new.html b/chrome/common/extensions/docs/templates/articles/whats_new.html new file mode 100644 index 0000000..fe62aa3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/whats_new.html @@ -0,0 +1,653 @@ +<h1>What's New in Extensions?</h1> +<!-- --> + +<p> +This page lists the API and manifest changes +made in recent releases. +</p> + +<ul> + <li> <a href="#22">Google Chrome 22</a> </li> + <li> <a href="#21">Google Chrome 21</a> </li> + <li> <a href="#20">Google Chrome 20</a> </li> + <li> <a href="#19">Google Chrome 19</a> </li> + <li> <a href="#18">Google Chrome 18</a> </li> + <li> <a href="#17">Google Chrome 17</a> </li> + <li> <a href="#16">Google Chrome 16</a> </li> + <li> <a href="#15">Google Chrome 15</a> </li> + <li> <a href="#14">Google Chrome 14</a> </li> + <li> <a href="#13">Google Chrome 13</a> </li> + <li> <a href="#12">Google Chrome 12</a> </li> + <li> <a href="#11">Google Chrome 11</a> </li> + <li> <a href="#10">Google Chrome 10</a> </li> + <li> <a href="#9">Google Chrome 9</a> </li> + <li> <a href="#8">Google Chrome 8</a> </li> + <li> <a href="#7">Google Chrome 7</a> </li> + <li> <a href="#6">Google Chrome 6</a> </li> +</ul> + +<h2 id="22"> Google Chrome 22 </h2> + +<h4> New APIs </h4> + <ul> + <li>The + <a href="alarms.html">alarms API</a> + lets you schedule code to run + periodically or at a specified time + in the future.</li> + </ul> + <ul> + <li>The + <a href="runtime.html">runtime API</a> + contains useful methods for dealing + with system-wide events. + </ul> + +<h4> Additions to Existing Features </h4> + <ul> + <li>Background pages can optionally be + non-persistent, using a feature we call + <a href="event_pages.html">event pages</a>. + Event pages run only while they're being used, + and will unload when idle to save resources. + </ul> + +<h2 id="21"> Google Chrome 21 </h2> + +<h4> New Features </h4> + <ul> + <li>The <a href="manifest.html#sandbox">sandbox manifest entry</a> allows + you to define some pages within your extension that are automatically run + in a low-privilege sandbox. This sandbox is not bound by the + <a href="contentSecurityPolicy.html">content_security_policy</a>. + <li>The <a href="input.ime.html">IME</a> API allows extensions to implement + <a href="http://en.wikipedia.org/wiki/Input_method">input method + editors</a> on Chrome OS. + </ul> + +<h4> Additions to Existing Features </h4> + <ul> + <li>The <a href="types.html#method-ChromeSetting-set" + >ChromeSetting.set()</a> method now has a + <code>regular_only</code> scope. + <li>The <a href="browsingData.html#type-RemovalOptions" + >browsingData.RemovalOptions</a> now has an <code>originTypes</code> + property. + <li>The <a href="management.html#method-uninstall" + >management.uninstall()</a> method now has a <code + >showConfirmDialog</code> parameter. + <li>The <a href="contextMenus.html#method-create" + >contextMenus.create()</a> method now allows you to specify unique + IDs for each item. This is intended to be used with the new + <a href="contextMenus.html#event-onClicked" + >contextMenus.onClicked</a> event, to distinguish the clicked item. + <li>The <a href="browserAction.html#method-setIcon" + >browserAction.setIcon()</a> and + <a href="pageAction.html#method-setIcon" + >pageAction.setIcon()</a> methods now accept optional callbacks. + <li>The <a href="privacy.html#property-websites" + >privacy.websites</a> namespace now has a <code + >protectedContentEnabled</code> property. + <li>The <code>index</code> parameter to the <a href="tabs.html#method-move" + >tabs.move()</a> method now accepts <code>-1</code> to indicate + that the tab should be placed at the end. + <li>The <code>windowId</code> parameter to the + <a href="tabs.html#method-highlight">tabs.highlight()</a> + method is now optional. + <li><a href="manifest.html#intents">Web intents</a> can now be used to + register content-type viewers. + </ul> + +<h2 id="20"> Google Chrome 20 </h2> + +<h4> New APIs </h4> + <ul> + <li>The + <a href="storage.html">storage API</a> + lets you store, retrieve, and + track changes to user data.</li> + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>Manifest version 1 was deprecated in Chrome 18 + and will be phased out according to the + <a href="manifestVersion.html">Manifest version 1 support schedule</a>.</li> + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>The <code>chrome.contextMenus</code> + <a href="contextMenus.html#method-create">create()</a> and + <a href="contextMenus.html#method-update">update()</a> + methods now have an <code>enabled</code> parameter.</li> + <li>The privacy API's <a href="privacy.html#property-services">services</a> object + now has a <code>spellingServiceEnabled</code> setting.</li> + <li>The <code>chrome.tabs</code> + <a href="tabs.html#method-executeScript">executeScript()</a> and + <a href="tabs.html#method-insertCSS">insertCSS()</a> + now accept a <code>runAt</code> parameter.</li> + </ul> + +<h4> Changes to existing APIs </h4> + + <ul> + <li>The <code>sendRequest()</code> method + has been deprecated in favor of the + <code>sendMessage()</code> method for both the + <a href="extension.html#method-sendMessage">extension API</a> and + <a href="tabs.html#method-sendMessage">tabs API</a>.</li> + <li>The <a href="external_extensions.html">external_extensions.json file</a> + has been deprecated in favor of individual + <code><extension-id>.json</code> files.</li> + </ul> + +<h2 id="19"> Google Chrome 19 </h2> + +<h4> New APIs </h4> + <ul> + <li>The <a href="browsingData.html">browsing data API</a> + lets you remove browsing data from a user's local profile. + <li>The <a href="topSites.html">top sites API</a> + gives you access to the top sites + that are displayed on the new tab page. + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>The new <a href="manifest.html#intents">intents</a> + field specifies all intent handlers provided by the extension. + </ul> + + <h4> Additions to existing APIs </h4> + <ul> + <li>The window API's <a href="windows.html#type-Window">Window</a> + object now has an <code>alwaysOnTop</code> property and + supports the "fullscreen" state. + <li>The <code>chrome.tabs</code> + <a href="tabs.html#method-query">query()</a> method + now has the <code>currentWindow</code> and + <code>lastFocusedWindow</code> parameters. + <li>The <a href="browserAction.html">browser action API</a> + has the following new getter functions: + <a href="browserAction.html#method-getTitle">getTitle</a>, + <a href="browserAction.html#method-getBadgeText">getBadgeText</a>, + <a href="browserAction.html#method-getBadgeBackgroundColor">getBadgeBackgr + oundColor</a>, and + <a href="browserAction.html#method-getPopup">getPopup</a>. + <li>The <a href="pageAction.html">page action API</a> + has the following new getter functions: + <a href="pageAction.html#method-getTitle">getTitle</a> and + <a href="pageAction.html#method-getPopup">getPopup</a>. + </ul> + +<h2 id="18"> Google Chrome 18 </h2> + +<h4> New APIs </h4> + <ul> + <li>The <a href="debugger.html">debugger API</a> + lets you use the Chrome Developer Tools + on one or more tabs remotely. + <li>The <a href="devtools.html">developer tools APIs</a> + provide support for extending Chrome Developer Tools. + The inspected window API lets you interact with the inspected window. + The network API lets you retrive information about network requests. + The panels API lets you add panels and sidebars. + <li>The <a href="pageCapture.html">page capture API</a> + lets you save a tab as MHTML. + <li> The <a href="privacy.html">privacy API</a> + lets you control usage of the features + in Chrome that can affect a user's privacy policy. + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>The new + <a href="manifest.html#manifest_version">manifest version</a> + field specifies the version of the manifest that your package requires. + As of Chrome 18, you should use + <a href="manifestVersion.html">manifest version 2</a>. + <li>The new + <a href="contentSecurityPolicy.html">Content Security Policy (CSP)</a> + field is used to define an extension's policies + towards the types of content + that can be loaded and executed by the extension. + <li>Most background pages only include a list of script files. + For these background pages, + you can use the new + <a href="background_pages.html">background.scripts</a> property + and Chrome will generate a background page for you. + <li>The new + <a href="manifest.html#web_accessible_resources">web_accessible_resources</a> + field specifies the paths of packaged resources + that are expected to be usable in the context of a web page. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>The <a href="windows.html#property-WINDOW_ID_CURRENT">windows API</a> + now has a <code>WINDOW_ID_CURRENT</code> property. + <li>The <code>chrome.tabs</code> + <a href="tabs.html#method-create">create()</a> and + <a href="tabs.html#method-update">update()</a> methods + now have an <code>openerTabId</code> parameter. + </ul> + +<h2 id="17"> Google Chrome 17 </h2> + +<h4> New APIs </h4> + <ul> + <li>The + <a href="webRequest.html">web request API</a> + lets you intercept, block, or + modify requests in-flight and + to observe and analyze traffic. + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>Permissions can be + <a href="permissions.html">optional</a> + for the content setting API, the web navigation API, and + the new web request API. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>The management API's + <a href="management.html#type-ExtensionInfo">ExtensionInfo</a> object + now has a <code>disabledReason</code> property. + </ul> + +<h4> Changes to existing APIs </h4> + + <ul> + <li>The <a href="omnibox.html">omnibox API</a> + now works in + <a href="manifest.html#incognito">split incognito mode</a>. + </ul> + +<h2 id="16"> Google Chrome 16 </h2> + +<h4> New APIs </h4> + <ul> + <li>The + <a href="webNavigation.html">web navigation API</a> + lets extensions receive notifications about the status + of navigation requests. + You can use this API to track navigation events. + <li>The + <a href="permissions.html">optional permissions API</a> + lets you control when users are presented with permission requests. + <li>The + <a href="contentSettings.html">content settings API</a> + lets extensions customize Chrome’s behavior + on a per-site basis instead of globally. + You can use this API to control whether websites can use features + such as cookies, JavaScript, and plug-ins. + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>The new + <a href="manifest.html#requirements">requirements</a> field + allows you to declare extension requirements up front. + For example, you can use this field + to specify that your app requires 3D graphics support + in order to use features such as CSS 3D Tranforms or WebGL. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>The new + <a href="tabs.html#method-query">chrome.tabs.query()</a> method + gets all tabs that have the specified properties or + all tabs if no properties are specified. + <li>The new + <a href="tabs.html#method-reload">chrome.tabs.reload()</a> method + reloads a tab and includes the option + to preserve the local cache of the reloaded tab. + <li>The management API's + <a href="management.html#type-ExtensionInfo">ExtensionInfo</a> object + now has an <code>updateURL</code> property. + <li>You can now limit the supported locales for an + <a href="external_extensions.html">external extension</a> + by adding the <code>supported_locales</code> attribute + to the <code>external_extensions.json</code>. + </ul> + +<h4> Changes to existing APIs </h4> + <ul> + <li>The methods <code>getAllInWindow()</code> and + <code>getSelected()</code> have been deprecated. + To get details about all tabs in the specified window, use + <a href="tabs.html#method-query">chrome.tabs.query()</a> + with the argument <code>{'windowId': windowID}</code>. + To get the tab that is selected in the specified window, use + <code>chrome.tabs.query()</code> + with the argument <code>{'active': true}</code>. + <li>You are no longer required + to specify the <code>tabID</code> for the + <a href="tabs.html#method-update">chrome.tabs.update()</a> method. + When not provided, + the <code>tabID</code> defaults + to the selected tab of the current window. + <li>External extension files on Mac OS can now be owned by users + within a wheel group (or an admin group). + <li>The "experimental" permission is no longer required + for the + <a href="windows.html#type-Window">window "panel"</a> type. + By default, the "panel" type creates a popup + unless the <code>--enable-panels</code> flag is set. + </ul> + +<h2 id="15"> Google Chrome 15 </h2> + +<h4> New APIs </h4> + +<ul> + <li>The <a href="webstore.html">webstore API</a> + lets you initiate app and extensions installations + <a href="http://code.google.com/chrome/webstore/docs/inline_installation.html">"inline"</a> + from your site. +</ul> + +<h4> Manifest changes </h4> + <ul> + <li>The new + <a href="manifest.html#offline_enabled">offline_enabled</a> field + lets you specify that your app works well even without an internet + connection. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>You can retrieve permission warnings using the new management API methods + <a href="management.html#method-getPermissionWarningsById">getPermissionWarningsById()</a> + and + <a href="management.html#method-getPermissionWarningsByManifest">getPermissionWarningsByManifest()</a>. + <li>The management API’s + <a href="management.html#type-ExtensionInfo">ExtensionInfo</a> object has + a new field, <code>offlineEnabled</code>. + <li>You can now <a href="i18n.html">internationalize</a> content script CSS + files by using <code>__MSG_messagename__</code> placeholders. + </ul> + +<h4> Changes to existing APIs </h4> + <ul> + <li>The callback for the <a href="tabs.html#method-update">tabs.update</a> + method is passed <code>null</code> instead of the tab details if the + extension does not have the "tabs" permission. + </ul> + +<h2 id="14"> Google Chrome 14 </h2> + +<h4> New APIs </h4> + <ul> + <li>The <a href="tts.html">tts API</a> + lets extensions generate speech from text. + <li>The <a href="ttsEngine.html">ttsEngine API</a> + lets extensions implement text-to-speech (TTS) engines. + <li>Extensions that are distributed through the Chrome Web Store + can now include Native Client modules. + No special manifest entry is necessary, as you can see from the + <a href="http://code.google.com/p/naclports/source/browse#svn%2Ftrunk%2Fsrc%2Fpackages%2Flibraries%2Fnethack-3.4.3">NetHack example</a>. + For more information, see the + <a href="http://blog.chromium.org/2011/08/native-client-brings-sandboxed-native.html">announcement</a> and the + <a href="http://code.google.com/chrome/nativeclient/">Native Client documentation</a>. + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>The new + <a href="manifest.html#content_security_policy">content_security_policy</a> field + can help prevent + <a href="http://blog.chromium.org/2011/07/writing-extensions-more-securely.html">cross-site scripting vulnerabilities</a> + in your extension. + <li>The new <a href="manifest.html#nacl_modules">nacl_modules</a> field + lets you register Native Client modules + as content handlers for MIME types. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li><a href="contextMenus.html">Context menu</a> items + can now appear even in documents + that have file:// or chrome:// URLs. + Previously, they were restricted to documents with + http:// or https:// URLs. + <li>An optional <code>drawAttention</code> field in + <a href="windows.html#method-update">chrome.windows.update()</a>'s + <code>updateInfo</code> object lets you specify that the window + should entice the user to change focus to it. + <li>The new + <a href="bookmarks.html#method-getSubTree">bookmarks.getSubTree()</a> + function lets you retrieve just part of the Bookmarks hierarchy. + </ul> + +<h4> Changes to existing APIs </h4> + <ul> + <li>The "tabs" permission is no longer required for + <a href="tabs.html#method-remove">tabs.remove</a> and + <a href="tabs.html#event-onRemoved">tabs.onRemoved</a>. + </ul> + +<h2 id="13"> Google Chrome 13 </h2> + +<h4> New APIs </h4> + <ul> + <li>The <a href="proxy.html">proxy API</a> + lets extensions manage Chrome's proxy settings. + <li>The + <a href="types.html#type-ChromeSetting">chrome.types.ChromeSetting</a> prototype + provides an interface to browser settings; + it's used by the proxy API. + <li> <em>Chrome OS only:</em> + The <a href="fileBrowserHandler.html">fileBrowserHandler API</a> + lets you extend the Chrome OS file browser. + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>A new <code>exclude_matches</code> item + in the "content_scripts" field + lets you target your content script more precisely. + For details, see + <a href="content_scripts.html#match-patterns-globs">Match patterns and globs</a>. + <li>New "clipboardRead" and "clipboardWrite" + <a href="manifest.html#permissions">permissions</a> + specify capabilities for <code>document.execCommand()</code>. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>Content scripts can now make + <a href="xhr.html">cross-origin XMLHttpRequests</a> + to the same sites that their parent extension can, + eliminating the need to relay these requests + through a background page. + <li>You can now use <code>@run-at</code> + in an imported Greasemonkey script + to control when the script is injected. + It works the same way as + <a href="content_scripts.html#run_at"><code>run_at</code></a> + in content scripts. + </ul> + +<h2 id="12"> Google Chrome 12 </h2> + +<h4> Additions to existing APIs </h4> + <ul> + <li>Two new <code>chrome.extension</code> + methods—<a href="extension.html#method-isAllowedFileSchemeAccess">isAllowedFileSchemeAccess()</a> and + <a href="extension.html#method-isAllowedIncognitoAccess">isAllowedIncognitoAccess()</a>—let you + determine whether your extension has increased access, + which the user specifies using the extensions management page + (<b>chrome://extensions</b>). + <li>The <a href="windows.html#method-create">chrome.windows.create()</a> + method can now take a <code>focused</code> value. + Previously, all new windows had the keyboard focus; + now you can create windows without interrupting the user's typing. + <li>If the manifest specifies "experimental" permission, + your extension can specify "panel" as the value of + the <code>type</code> field in + the <a href="windows.html#method-create">chrome.windows.create()</a> + method + or the <a href="windows.html#type-Window">Window</a> type. + <li>The <a href="cookies.html#event-onChanged">onChanged</a> + event of <code>chrome.cookies</code> + now has a <code>cause</code> parameter. + <li>The <code>chrome.contextMenus</code> + <a href="contextMenus.html#method-create">create()</a> and + <a href="contextMenus.html#method-update">update()</a> + methods now let you specify a context value of "frame". + </ul> + +<h2 id="11"> Google Chrome 11 </h2> + +<h4> Changes to existing APIs </h4> + <ul> + <li>For security reasons, you can no longer call + <a href="tabs.html#method-captureVisibleTab">chrome.tab.captureVisibleTab()</a> + on just any tab. + Instead, you now must have + <a href="manifest.html#permissions">host permission</a> + for the URL displayed by that tab. + To get the previous behavior, + specify <code><all_urls></code> for the host permission. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>The management API's + <a href="management.html#type-ExtensionInfo">ExtensionInfo</a> object + now has a <code>homepageUrl</code> property. + <li>The management API now lets you get the icons of + disabled apps and extensions. + Also, you can now modify the regular icon's URL + to get its disabled equivalent. + See <a href="management.html#type-IconInfo">IconInfo</a> for details. + <li>The cookies API + <a href="cookies.html#method-set">set()</a> + and <a href="cookies.html#method-remove">remove()</a> methods + can now take callbacks. + </ul> + +<h2 id="10"> Google Chrome 10 </h2> + +<h4> Manifest changes </h4> + <ul> + <li>The new <a href="manifest.html#bg">background</a> permission + extends the life of Chrome, + allowing your extension or app + to run even when Chrome has no windows open. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>The <a href="windows.html#method-create">chrome.windows.create()</a> + method now has a <code>tabId</code> field. + You can use it to move a tab or panel into a new window. + <p class="note"> + <b>Note:</b> + This change was incorrectly attributed to Chrome 9 + in previous release notes. + </ul> + +<h2 id="9"> Google Chrome 9 </h2> + +<h4> New APIs </h4> + <ul> + <li>The <a href="omnibox.html">omnibox API</a> allows you to + register a keyword with Chrome's address bar. + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>The <a href="manifest.html#homepage_url">homepage_url</a> field + lets you specify the extension or app's homepage. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>The <a href="tabs.html#type-Tab">Tab</a> object + now has a <code>pinned</code> property + that's reflected in various <code>chrome.tabs</code> methods. + For example, + you can <a href="tabs.html#method-create">create</a> + a pinned tab. + <li>The <a href="windows.html#method-create">chrome.windows.create()</a> + method can now take a list of URLs, + letting you create multiple tabs in the new window. + <li>The new + <a href="management.html#method-get">chrome.management.get()</a> method + lets you get information about the specified extension or app. + </ul> + + +<h2 id="8"> Google Chrome 8 </h2> + +<p> +We took a break for Chrome 8. +No API or manifest changes worth noting. +</p> + + +<h2 id="7"> Google Chrome 7 </h2> + +<h4> New APIs </h4> + <ul> + <li>All users can now install + <a href="http://code.google.com/chrome/apps/index.html">apps</a>; + packaged apps can use extension APIs. + <li>The <a href="management.html">management API</a> + lets you work with installed apps and extensions. + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>Introduced <a href="manifest.html#incognito">split incognito</a> + mode as the default for installable web apps + (also available to extensions). + <li>The <a href="tabs.html">tabs API</a> + <code>create()</code> and <code>update()</code> methods + no longer require the "tabs" permission, removing one common cause of + <a href="permission_warnings.html">scary dialogs</a>. + </ul> + + +<h2 id="6">Google Chrome 6</h2> + +<h4> New APIs </h4> + <ul> + <li>The <a href="contextMenus.html">context menus API</a> allows you to + add context menus to pages or specific objects on a page. + <li>The <a href="cookies.html">cookies API</a> allows you to manage the + browser's cookie system. + <li>The <a href="idle.html">idle API</a> allows you to detect when the + machine's idle state changes. + </ul> + +<h4> Additions to existing APIs </h4> + <ul> + <li>The <a + href="extension.html#method-getViews">chrome.extension.getViews()</a> + method can now return popup views. + <li>A new <a + href="windows.html#property-WINDOW_ID_NONE">WINDOW_ID_NONE</a> constant + identifies when focus shifts away from the browser. + <li>The new <a + href="tabs.html#method-getCurrent">chrome.tabs.getCurrent()</a> method + returns the tab associated with the currently executing script. + </ul> + +<h4> Manifest changes </h4> + <ul> + <li>The <a href="manifest.html#geolocation">geolocation</a> permission + gives an extension access to the user's physical location. + <li><a href="match_patterns.html">Match patterns</a> can now select all + schemes or all URLs. + <li>Access to file:/// URLs no longer triggers the "access to your machine" + security warning, but now requires user opt-in from the extensions + management page. + </ul> diff --git a/chrome/common/extensions/docs/templates/articles/xhr.html b/chrome/common/extensions/docs/templates/articles/xhr.html new file mode 100644 index 0000000..9dd3150 --- /dev/null +++ b/chrome/common/extensions/docs/templates/articles/xhr.html @@ -0,0 +1,150 @@ +<h1>Cross-Origin XMLHttpRequest</h1> + + +<p id="classSummary"> +Regular web pages can use the +<a href="http://www.w3.org/TR/XMLHttpRequest/">XMLHttpRequest</a> +object to send and receive data from remote servers, +but they're limited by the +<a href="http://en.wikipedia.org/wiki/Same_origin_policy">same origin policy</a>. +Extensions aren't so limited. +An extension can talk to remote servers outside of its origin, +as long as it first requests cross-origin permissions.</p> + +<h2 id="extension-origin">Extension origin</h2> +<p>Each running extension exists within its own separate security origin. Without +requesting additional privileges, the extension can use +XMLHttpRequest to get resources within its installation. For example, if +an extension contains a JSON configuration file called <code>config.json</code>, +in a <code>config_resources</code> folder, the extension can retrieve the file's contents like +this:</p> + +<pre> +var xhr = new XMLHttpRequest(); +xhr.onreadystatechange = handleStateChange; // Implemented elsewhere. +xhr.open("GET", chrome.extension.getURL('/config_resources/config.json'), true); +xhr.send(); +</pre> + +<p>If the extension attempts to use a security origin other than itself, +say http://www.google.com, +the browser disallows it +unless the extension has requested the appropriate cross-origin permissions. +</p> + +<h2 id="requesting-permission">Requesting cross-origin permissions</h2> + +<p>By adding hosts or host match patterns (or both) to the +<a href="manifest.html#permissions">permissions</a> section of the +<a href="manifest.html">manifest</a> file, the extension can request access to +remote servers outside of its origin.</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "http://www.google.com/" + ]</b>, + ... +}</pre> + +<p>Cross-origin permission values can be fully qualified host names, +like these:</p> + +<ul> + <li> "http://www.google.com/" </li> + <li> "http://www.gmail.com/" </li> +</ul> + +<p>Or they can be match patterns, like these:</p> + +<ul> + <li> "http://*.google.com/" </li> + <li> "http://*/" </li> +</ul> + +<p> +A match pattern of "http://*/" allows HTTP access to all reachable domains. +Note that here, +match patterns are similar to <a href="match_patterns.html">content script +match patterns</a>, +but any path information following the host is ignored.</p> + +<p>Also note that access is granted both by host and by scheme. If an extension +wants both secure and non-secure HTTP access to a given host or set +of hosts, it must declare the permissions separately:</p> + +<pre>"permissions": [ + "http://www.google.com/", + "https://www.google.com/" +] +</pre> + +<h2 id="security-considerations">Security considerations</h2> + +<p> +When using resources retrieved via XMLHttpRequest, your background page should +be careful not to fall victim to <a +href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross-site +scripting</a>. Specifically, avoid using dangerous APIs such as the below: +</p> +<pre>background.html +=============== +var xhr = new XMLHttpRequest(); +xhr.open("GET", "http://api.example.com/data.json", true); +xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + // WARNING! Might be evaluating an evil script! + var resp = eval("(" + xhr.responseText + ")"); + ... + } +} +xhr.send(); + +background.html +=============== +var xhr = new XMLHttpRequest(); +xhr.open("GET", "http://api.example.com/data.json", true); +xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + // WARNING! Might be injecting a malicious script! + document.getElementById("resp").innerHTML = xhr.responseText; + ... + } +} +xhr.send(); +</pre> +<p> +Instead, prefer safer APIs that do not run scripts: +</p> +<pre>background.html +=============== +var xhr = new XMLHttpRequest(); +xhr.open("GET", "http://api.example.com/data.json", true); +xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + // JSON.parse does not evaluate the attacker's scripts. + var resp = JSON.parse(xhr.responseText); + } +} +xhr.send(); + +background.html +=============== +var xhr = new XMLHttpRequest(); +xhr.open("GET", "http://api.example.com/data.json", true); +xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + // innerText does not let the attacker inject HTML elements. + document.getElementById("resp").innerText = xhr.responseText; + } +} +xhr.send(); +</pre> +<p> +Additionally, be especially careful of resources retrieved via HTTP. If your +extension is used on a hostile network, an network attacker (aka a <a +href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">"man-in-the-middle"</a>) +could modify the response and, potentially, attack your extension. Instead, +prefer HTTPS whenever possible. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/bookmarks.html b/chrome/common/extensions/docs/templates/intros/bookmarks.html new file mode 100644 index 0000000..7ebe4f1 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/bookmarks.html @@ -0,0 +1,89 @@ +<p id="classSummary"> +Use the <code>chrome.bookmarks</code> module to create, organize, +and otherwise manipulate bookmarks. +Also see <a href="override.html">Override Pages</a>, +which you can use to create a custom Bookmark Manager page. +</p> + +<img src="{{static}}/images/bookmarks.png" + width="210" height="147" alt="Clicking the star adds a bookmark" /> + +<h2 id="manifest">Manifest</h2> +<p>You must declare the "bookmarks" permission +in the <a href="manifest.html">extension manifest</a> +to use the bookmarks API. +For example:</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "bookmarks" + ]</b>, + ... +}</pre> + +<h2 id="description">Objects and properties</h2> + +<p> +Bookmarks are organized in a tree, +where each node in the tree +is either a bookmark or a folder +(sometimes called a <em>group</em>). +Each node in the tree +is represented by a +<a href="#type-BookmarkTreeNode"><code>BookmarkTreeNode</code></a> object. +</p> + +<p> +<code>BookmarkTreeNode</code> properties +are used throughout the <code>chrome.bookmarks</code> API. +For example, when you call +<a href="#method-create"><code>create()</code></a>, +you pass in the new node's parent (<code>parentId</code>), +and, optionally, the node's +<code>index</code>, <code>title</code>, and <code>url</code> properties. +See <a href="#type-BookmarkTreeNode"><code>BookmarkTreeNode</code></a> +for information about the properties a node can have. +</p> + +<p class="note"><b>Note:</b> You cannot use this API to add or remove entries +in the root folder. You also cannot rename, move, or remove the special +"Bookmarks Bar" and "Other Bookmarks" folders.</p> + +<h2 id="overview-examples">Examples</h2> + +<p> +The following code creates a folder with the title "Extension bookmarks". +The first argument to <code>create()</code> specifies properties +for the new folder. +The second argument defines a function +to be executed after the folder is created. +</p> + +<pre> +chrome.bookmarks.create({'parentId': bookmarkBar.id, + 'title': 'Extension bookmarks'}, + function(newFolder) { + console.log("added folder: " + newFolder.title); +}); +</pre> + +<p> +The next snippet creates a bookmark pointing to +the developer documentation for extensions. +Since nothing bad will happen if creating the bookmark fails, +this code doesn't bother to define a callback function. +</p> + +<pre> +chrome.bookmarks.create({'parentId': extensionsFolderId, + 'title': 'Extensions doc', + 'url': 'http://code.google.com/chrome/extensions'}); +</pre> + +<p> +For an example of using this API, see the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/bookmarks/basic/">basic bookmarks sample</a>. +For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/browserAction.html b/chrome/common/extensions/docs/templates/intros/browserAction.html new file mode 100644 index 0000000..d4c7476 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/browserAction.html @@ -0,0 +1,172 @@ +<p>Use browser actions to put icons + in the main Google Chrome toolbar, + to the right of the address bar. + In addition to its <a href="#icon">icon</a>, + a browser action can also have + a <a href="#tooltip">tooltip</a>, + a <a href="#badge">badge</a>, + and a <a href="#popups">popup</a>. + </p> + +<p> +In the following figure, +the multicolored square +to the right of the address bar +is the icon for a browser action. +A popup is below the icon. +</p> + +<img src="{{static}}/images/browser-action.png" + width="363" height="226" /> + +<p> +If you want to create an icon that isn't always visible, +use a <a href="pageAction.html">page action</a> +instead of a browser action. +</p> + +<p class="caution"> +<strong>Note:</strong> +Packaged apps cannot use browser actions. +</p> + + + +<h2 id="manifest">Manifest</h2> + +<p> +Register your browser action in the +<a href="manifest.html">extension manifest</a> +like this: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"browser_action": { + "default_icon": "images/icon19.png", <em>// optional</em> + "default_title": "Google Mail", <em>// optional; shown in tooltip</em> + "default_popup": "popup.html" <em>// optional</em> + }</b>, + ... +}</pre> + +<h2 id="ui">Parts of the UI</h2> + +<p> +A browser action can have an <a href="#icon">icon</a>, +a <a href="#tooltip">tooltip</a>, +a <a href="#badge">badge</a>, +and a <a href="#popups">popup</a>. +</p> + +<h3 id="icon">Icon</h3> + +<p>Browser action icons can be up to 19 pixels wide and high. + Larger icons are resized to fit, but for best results, + use a 19-pixel square icon.</p> + +<p>You can set the icon in two ways: + using a static image or using the + HTML5 <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html">canvas element</a>. + Using static images is easier for simple applications, + but you can create more dynamic UIs — + such as smooth animation — + using the canvas element. + </p> + +<p>Static images can be in any format WebKit can display, + including BMP, GIF, ICO, JPEG, or PNG. + </p> + +<p>To set the icon, +use the <b>default_icon</b> field of <b>browser_action</b> +in the <a href="#manifest">manifest</a>, +or call the <a href="#method-setIcon">setIcon()</a> method. + + +<h3 id="tooltip">Tooltip</h3> + +<p> +To set the tooltip, +use the <b>default_title</b> field of <b>browser_action</b> +in the <a href="#manifest">manifest</a>, +or call the <a href="#method-setTitle">setTitle()</a> method. +You can specify locale-specific strings for the <b>default_title</b> field; +see <a href="i18n.html">Internationalization</a> for details. +</p> + +<h3 id="badge">Badge</h3> + +<p>Browser actions can optionally display a <em>badge</em> — + a bit of text that is layered over the icon. + Badges make it easy to update the browser action + to display a small amount of information + about the state of the extension.</p> + +<p>Because the badge has limited space, + it should have 4 characters or less. + </p> + +<p> +Set the text and color of the badge using +<a href="#method-setBadgeText">setBadgeText()</a> and +<a href="#method-setBadgeBackgroundColor">setBadgeBackgroundColor()</a>, +respectively. + +</p> + + +<h3 id="popups">Popup</h3> + +<p>If a browser action has a popup, + the popup appears when the user clicks the icon. + The popup can contain any HTML contents that you like, + and it's automatically sized to fit its contents. + </p> + +<p> +To add a popup to your browser action, +create an HTML file with the popup's contents. +Specify the HTML file in the <b>default_popup</b> field of <b>browser_action</b> +in the <a href="#manifest">manifest</a>, or call the +<a href="#method-setPopup">setPopup()</a> method. +</p> + +<h2>Tips</h2> + +<p>For the best visual impact, + follow these guidelines:</p> + +<ul> + <li><b>Do</b> use browser actions for features + that make sense on most pages. + <li><b>Don't</b> use browser actions for features + that make sense for only a few pages. + Use <a href="pageAction.html">page actions</a> instead. + <li><b>Do</b> use big, colorful icons that make the most of + the 19x19-pixel space. + Browser action icons should seem a little bigger + and heavier than page action icons. + <li><b>Don't</b> attempt to mimic + Google Chrome's monochrome "wrench" icon. + That doesn't work well with themes, and anyway, + extensions should stand out a little. + <li><b>Do</b> use alpha transparency + to add soft edges to your icon. + Because many people use themes, + your icon should look nice + on a variety of background colors. + <li><b>Don't</b> constantly animate your icon. + That's just annoying. +</ul> + +<h2 id="examples"> Examples </h2> + +<p> +You can find simple examples of using browser actions in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/browserAction/">examples/api/browserAction</a> +directory. +For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/browsingData.html b/chrome/common/extensions/docs/templates/intros/browsingData.html new file mode 100644 index 0000000..36080ca --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/browsingData.html @@ -0,0 +1,157 @@ +<p id="classSummary"> + Use the <code>chrome.browsingData</code> module to remove browsing data from a + user's local profile. +</p> + +<h2 id="manifest">Manifest</h2> + +<p> + You must declare the "browsingData" permission in the + <a href="manifest.html">extension manifest</a> to use this API. +</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "browsingData", + ]</b>, + ... +}</pre> + +<h2 id="usage">Usage</h2> + +<p> + The simplest use-case for this API is a a time-based mechanism for clearing a + user's browsing data. Your code should provide a timestamp which indicates the + historical date after which the user's browsing data should be removed. This + timestamp is formatted as the number of milliseconds since the Unix epoch + (which can be retrieved from a JavaScript <code>Date</code> object via the + <code>getTime</code> method). +</p> + +<p> + For example, to clear all of a user's browsing data from the last week, you + might write code as follows: +</p> + +<pre>var callback = function () { + // Do something clever here once data has been removed. +}; + +var millisecondsPerWeek = 1000 * 60 * 60 * 24 * 7; +var oneWeekAgo = (new Date()).getTime() - millisecondsPerWeek; +chrome.browsingData.remove({ + "since": oneWeekAgo +}, { + "appcache": true, + "cache": true, + "cookies": true, + "downloads": true, + "fileSystems": true, + "formData": true, + "history": true, + "indexedDB": true, + "localStorage": true, + "pluginData": true, + "passwords": true, + "webSQL": true +}, callback);</pre> + +<p> + The <code>chrome.browsingData.remove</code> method allows you to remove + various types of browsing data with a single call, and will be much faster + than calling multiple more specific methods. If, however, you only want to + clear one specific type of browsing data (cookies, for example), the more + granular methods offer a readable alternative to a call filled with JSON. +</p> + +<pre>var callback = function () { + // Do something clever here once data has been removed. +}; + +var millisecondsPerWeek = 1000 * 60 * 60 * 24 * 7; +var oneWeekAgo = (new Date()).getTime() - millisecondsPerWeek; +chrome.browsingData.removeCookies({ + "since": oneWeekAgo +}, callback);</pre> + +<p class="caution"> + <strong>Important</strong>: Removing browsing data involves a good deal of + heavy lifting in the background, and can take <em>tens of seconds</em> to + complete, depending on a user's profile. You should use the callback mechanism + to keep your users up to date on the removal's status. +</p> + +<h2 id="origin_types">Origin Types</h2> + +<p> + Adding an <code>originType</code> property to the API's options object allows + you to specify which types of origins ought to be effected. Currently, origins + are divided into three categories: +</p> +<ul> + <li> + <code>unprotectedWeb</code> covers the general case of websites that users + visit without taking any special action. If you don't specify an + <code>originType</code>, the API defaults to removing data from unprotected + web origins. + </li> + <li> + <code>protectedWeb</code> covers those web origins that have been installed + as hosted applications. Installing <a href="https://chrome.google.com/webstore/detail/aknpkdffaafgjchaibgeefbgmgeghloj"> + Angry Birds</a>, for example, protects the origin + <code>http://chrome.angrybirds.com</code>, and removes it from the + <code>unprotectedWeb</code> category. Please do be careful when triggering + deletion of data for these origins: make sure your users know what they're + getting, as this will irrevocably remove their game data. No one wants to + knock tiny pig houses over more often than necessary. + </li> + <li> + <code>extension</code> covers origins under the + <code>chrome-extensions:</code> scheme. Removing extension data is, again, + something you should be very careful about. + </li> +</ul> +<p> + We could adjust the previous example to remove only data from protected + websites as follows: +</p> +<pre>var callback = function () { + // Do something clever here once data has been removed. +}; + +var millisecondsPerWeek = 1000 * 60 * 60 * 24 * 7; +var oneWeekAgo = (new Date()).getTime() - millisecondsPerWeek; +chrome.browsingData.remove({ + "since": oneWeekAgo, + <b>"originType": { + "protectedWeb": true + }</b> +}, { + "appcache": true, + "cache": true, + "cookies": true, + "downloads": true, + "fileSystems": true, + "formData": true, + "history": true, + "indexedDB": true, + "localStorage": true, + "pluginData": true, + "passwords": true, + "webSQL": true +}, callback);</pre> + +<p class="caution"> + <strong>Seriously</strong>: Be careful with <code>protectedWeb</code> and + <code>extension</code>. These are destructive operations that your users + will write angry email about if they're not well-informed about what to + expect when your extension removes data on their behalf. +</p> + +<h2 id="samples">Examples</h2> +<p> + Samples for the <code>browsingData</code> API are available + <a href="http://code.google.com/chrome/extensions/trunk/samples.html#chrome.browsingData">on the samples page</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/commands.html b/chrome/common/extensions/docs/templates/intros/commands.html new file mode 100644 index 0000000..283ea1a --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/commands.html @@ -0,0 +1,74 @@ +<p> +The commands API allows you to add keyboard shortcuts that trigger actions in +your extension. An action can be opening the browser action or page action popup +or sending a command to the extension. +</p> + +<h2 id="manifest">Manifest</h2> +<p> +You must declare the "commands" permission in your extension's manifest to use +this API and set manifest_version to (at least) 2. +</p> + +<pre>{ + "name": "My extension", + ... +<b> "permissions": [ + "commands", + ]</b>, + ... +}</pre> + +<h2 id="usage">Usage</h2> +<p>The commands API allows you to define specific commands, and bind them to a +default key combination. Each command your extension accepts must be listed in +the manifest as an attribute of the 'commands' manifest key. Note: Combinations +that involve Ctrl+Alt are not permitted in order to avoid conflicts with the +AltGr key.</p> + +<pre>{ + "name": "My extension", + ... +<b> "commands": { + "toggle-feature-foo": { + "suggested_key": { + "default": "Ctrl+Shift+Y", + "mac": "Command+Shift+Y" + }, + "description": "Toggle feature foo" + }, + "_execute_browser_action": { + "suggested_key": { + "windows": "Ctrl+Shift+Y", + "mac": "Command+Shift+Y", + "chromeos": "Ctrl+Shift+U", + "linux": "Ctrl+Shift+J" + } + }, + "_execute_page_action": { + "suggested_key": { + "default": "Ctrl+E" + "windows": "Alt+P", + "mac": "Option+P", + } + } + }</b>, + ... +}</pre> + +<p>In your background page, you can bind a handler to each of the commands +defined in the manifest (except for '_execute_browser_action' and +'_execute_page_action') via onCommand.addListener. For example:</p> + +<pre> +chrome.commands.onCommand.addListener(function(command) { + console.log('Command:', command); +}); +</pre> + +<p>The '_execute_browser_action' and '_execute_page_action' commands are +reserved for the action of opening your extension's popups. They won't normally +generate events that you can handle. If you need to take action based on your +popup opening, consider listening for an 'onDomReady' event inside your popup's +code. +</p> diff --git a/chrome/common/extensions/docs/templates/intros/contentSettings.html b/chrome/common/extensions/docs/templates/intros/contentSettings.html new file mode 100644 index 0000000..2353b15 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/contentSettings.html @@ -0,0 +1,148 @@ +<p> +The content settings module allows you to change settings that control whether +websites can use features such as cookies, JavaScript, and plug-ins. +More generally speaking, content settings allow you to customize Chrome's +behavior on a per-site basis instead of globally.</p> +<p> +</p> + +<h2 id="manifest">Manifest</h2> +<p>You must declare the "contentSettings" permission +in your extension's manifest to use the API. +For example:</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "contentSettings" + ]</b>, + ... +}</pre> + + +<h2 id="patterns">Content setting patterns</h2> +<p> +You can use patterns to specify the websites that each content setting affects. +For example, <code>http://*.youtube.com/*</code> specifies youtube.com and all +of its subdomains. The syntax for content setting patterns is the same as for +<a href="match_patterns.html">match patterns</a>, with a few differences: +<ul><li>For <code>http</code>, +<code>https</code>, and <code>ftp</code> URLs, the path must be a wildcard +(<code>/*</code>). For <code>file</code> URLs, the path must be completely +specified and <strong>must not</strong> contain wildcards.</li> +<li>In contrast to match patterns, content setting patterns can specify a port +number. If a port number is specified, the pattern only matches websites with +that port. If no port number is specified, the pattern matches all ports. +</li> +</ul> +</p> + +<h3 id="pattern-precedence">Pattern precedence</h3> +<p> +When more than one content setting rule applies for a given site, the rule with +the more specific pattern takes precedence. +</p> +<p>For example, the following patterns are ordered by precedence:</p> +<ol> +<li><code>http://www.example.com/*</code></li> +<li><code>http://*.example.com/*</code> (matching +example.com and all subdomains)</li> +<li><code><all_urls></code> (matching every URL)</li> +</ol> +<p> +Three kinds of wildcards affect how specific a pattern is: +</p> +<ul> +<li>Wildcards in the port (for example +<code>http://www.example.com:*/*</code>)</li> +<li>Wildcards in the scheme (for example +<code>*://www.example.com:123/*</code>)</li> +<li>Wildcards in the hostname (for example +<code>http://*.example.com:123/*</code>)</li> +</ul> +<p> +If a pattern is more specific than another pattern in one part but less specific +in another part, the different parts are checked in the following order: +hostname, scheme, port. For example, the following patterns are ordered by +precedence:</p> +<ol> +<li><code>http://www.example.com:*/*</code><br> +Specifies the hostname and scheme.</li> +<li><code>*:/www.example.com:123/*</code><br> +Not as high, because although it specifies the hostname, it doesn't specify +the scheme.</li> +<li><code>http://*.example.com:123/*</code><br> +Lower because although it specifies the port and scheme, it has a wildcard +in the hostname.</li> +</ol> + +<h2 id="primary-secondary">Primary and secondary patterns</h2> +<p> +The URL taken into account when deciding which content setting to apply depends +on the content type. For example, for +<a href="#property-notifications">notifications</a> settings are +based on the URL shown in the omnibox. This URL is called the "primary" URL.</p> +<p> +Some content types can take additional URLs into account. For example, +whether a site is allowed to set a +<a href="#property-cookies">cookie</a> is decided based on the URL +of the HTTP request (which is the primary URL in this case) as well as the URL +shown in the omnibox (which is called the "secondary" URL). +</p> +<p> +If multiple rules have primary and secondary patterns, the rule with the more +specific primary pattern takes precedence. If there multiple rules have the same +primary pattern, the rule with the more specific secondary pattern takes +precedence. For example, the following list of primary/secondary pattern pairs +is ordered by precedence:</p> +<table> +<tr><th>Precedence</th><th>Primary pattern</th><th>Secondary pattern</th> +<tr> + <td>1</td> + <td><code>http://www.moose.com/*</code>, </td> + <td><code>http://www.wombat.com/*</code></td> +</tr><tr> + <td>2</td> + <td><code>http://www.moose.com/*</code>, </td> + <td><code><all_urls></code></td> +</tr><tr> + <td>3</td> + <td><code><all_urls></code>, </td> + <td><code>http://www.wombat.com/*</code></td> +</tr><tr> + <td>4</td> + <td><code><all_urls></code>, </td> + <td><code><all_urls></code></td> +</tr> +</table> + +<h2 id="resource-identifiers">Resource identifiers</h2> +<p> +Resource identifiers allow you to specify content settings for specific +subtypes of a content type. Currently, the only content type that supports +resource identifiers is <a href="#property-plugins"><code>plugins</code></a>, +where a resource identifier identifies a specific plug-in. When applying content +settings, first the settings for the specific plug-in are checked. If there are +no settings found for the specific plug-in, the general content settings for +plug-ins are checked. +</p> +<p> +For example, if a content setting rule has the resource identifier +<code>adobe-flash-player</code> and the pattern <code><all_urls></code>, +it takes precedence over a rule without a resource identifier and the pattern +<code>http://www.example.com/*</code>, even if that pattern is more specific. +</p> +<p> +You can get a list of resource identifiers for a content type by calling the +<a href="contentSettings.html#method-ContentSetting-getResourceIdentifiers"> +<code>getResourceIdentifiers()</code></a> method. The returned list +can change with the set of installed plug-ins on the user's machine, but Chrome +tries to keep the identifiers stable across plug-in updates. +</p> + +<h2 id="examples">Examples</h2> + +<p> +You can find samples of this API on the +<a href="samples.html#contentSettings">sample page</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/contextMenus.html b/chrome/common/extensions/docs/templates/intros/contextMenus.html new file mode 100644 index 0000000..685ef16 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/contextMenus.html @@ -0,0 +1,55 @@ +<p> +The context menus module allows you +to add items to Google Chrome's context menu. +</p> + +<p> +You can choose what types of objects +your context menu additions apply to, +such as images, hyperlinks, and pages. +</p> + +<p> +You can create as many context menu items +as you need, but if more than one +from your extension is visible at once, +Google Chrome automatically collapses them +into a single parent menu. +</p> + +<p> +Context menu items can appear in any document +(or frame within a document), +even those with file:// or chrome:// URLs. +To control which documents your items can appear in, +specify the documentUrlPatterns field +when you call the create() or update() method. +</p> + +<h2 id="manifest">Manifest</h2> +<p>You must declare the "contextMenus" permission +in your extension's manifest to use the API. +Also, you should specify a 16x16-pixel icon +for display next to your menu item. +For example: +</p> + +<pre>{ + "name": "My extension", + ... + "permissions": [ + <b>"contextMenus"</b> + ], + "icons": { + <b>"16": "icon-bitty.png",</b> + "48": "icon-small.png", + "128": "icon-large.png" + }, + ... +}</pre> + +<h2 id="examples">Examples</h2> + +<p> +You can find samples of this API on the +<a href="samples.html#contextMenus">sample page</a>.
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/cookies.html b/chrome/common/extensions/docs/templates/intros/cookies.html new file mode 100644 index 0000000..2e7c2dc --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/cookies.html @@ -0,0 +1,30 @@ +<h2 id="manifest">Manifest</h2> + +<p>To use the cookies API, +you must declare the "cookies" permission in your manifest, +along with <a href="manifest.html#permissions">host permissions</a> +for any hosts whose cookies +you want to access. +For example:</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "cookies", + "*://*.google.com" + ]</b>, + ... +}</pre> + +<h2 id="examples"> Examples </h2> + +<p> +You can find a simple example +of using the cookies API in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/cookies/">examples/api/cookies</a> +directory. +For other examples +and for help in viewing the source code, +see <a href="samples.html">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/debugger.html b/chrome/common/extensions/docs/templates/intros/debugger.html new file mode 100644 index 0000000..a815425 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/debugger.html @@ -0,0 +1,41 @@ +<h2 id="manifest">Notes</h2> + +<p> +Debugger API serves as an alternate transport for Chrome's +<a href="http://code.google.com/chrome/devtools/docs/remote-debugging.html"> +remote debugging protocol</a>. Use <code>chrome.debugger</code> +to attach to one or more tabs to instrument network interaction, debug +JavaScript, mutate the DOM and CSS, etc. Use the Debuggee tabId to target tabs +with sendCommand and route events by <code>tabId</code> from onEvent callbacks. +</p> + +<p> +As of today, attaching to the tab by means of the debugger API +and using embedded Chrome DevTools with that tab are mutually exclusive. +If user invokes Chrome DevTools while extension is attached to the tab, +debugging session is terminated. Extension can re-establish it later. +</p> + +<h2 id="manifest">Manifest</h2> + +<p> +You must declare the "debugger" permission in your extension's manifest +to use this API. +</p> + +<pre>{ + "name": "My extension", + ... +<b> "permissions": [ + "debugger", + ]</b>, + ... +}</pre> + + +<h2 id="examples">Examples</h2> + +<p> +You can find samples of this API in +<a href="samples.html#debugger">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html b/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html new file mode 100644 index 0000000..9f212a8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html @@ -0,0 +1,222 @@ +<h2 id="notes">Notes</h2> + +<p> +Use the <code>chrome.declarativeWebRequest</code> module to intercept, block, or +modify requests in-flight. It is significantly faster than the <a + href="webRequest.html"><code>chrome.webRequest</code> API</a> because you can +register rules that are evaluated in the browser rather than the +JavaScript engine which reduces roundtrip latencies and allows for very high +efficiency. +</p> + +<h2 id="manifest">Manifest</h2> + +<p> +You must declare the "declarativeWebRequest" permission in the +<a href="manifest.html">extension manifest</a> to use this API, +along with <a href="manifest.html#permissions">host permissions</a> for any +hosts whose network requests you want to access. +</p> + +<pre>{ + "name": "My extension", + ... +<b> "permissions": [ + "declarativeWebRequest", + "*://*.google.com" + ]</b>, + ... +}</pre> + +<h2 id="rules">Rules</h2> + +<p> +The Declarative Web Request API follows the concepts of the <a + href="events.html#declarative">Declarative API</a>. You can register rules to +the <code>chrome.declarativeWebRequest.onRequest</code> event object. +</p> + +<p> +The Declarative Web Request API supports a single type of match criteria, the +<code>RequestMatcher</code>. The <code>RequestMatcher</code> matches network +requests if and only if all listed criteria are met. The following +<code>RequestMatcher</code> would match a network request when the user enters +"http://www.example.com" in the URL bar: +</p> + +<pre> +var matcher = new chrome.declarativeWebRequest.RequestMatcher({ + url: { hostSuffix: 'example.com', schemes: ['http'] }, + resourceType: ['main_frame'] + }); +</pre> + +<p> +Requests to "https://www.example.com" would be rejected by the +<code>RequestMatcher</code> due to the scheme. Also all requests for an embedded +iframe would be rejected due to the <code>resourceType</code>. +</p> + +<p class="note"> +<strong>Note:</strong> All conditions and actions are created via a constructor +as shown in the example above. +<p> + +<p> +In order to cancel all requests to "example.com", you can define a rule as +follows: +</p> +<pre> +var rule = { + conditions: [ + new chrome.declarativeWebRequest.RequestMatcher({ + url: { hostSuffix: 'example.com' } }) + ], + actions: [ + new chrome.declarativeWebRequest.CancelRequest() + ]}; +</pre> + +<p> +In order to cancel all requests to "example.com" and "foobar.com", you can add a +second condition, as each condition is sufficient to trigger all specified +actions: +</p> +<pre> +var rule2 = { + conditions: [ + new chrome.declarativeWebRequest.RequestMatcher({ + url: { hostSuffix: 'example.com' } }), + new chrome.declarativeWebRequest.RequestMatcher({ + url: { hostSuffix: 'foobar.com' } }) + ], + actions: [ + new chrome.declarativeWebRequest.CancelRequest() + ]}; +</pre> + +<p> +Register rules as follows: +</p> +<pre> +chrome.declarativeWebRequest.onRequest.addRules([rule2]); +</pre> + +<p class="note"> +<strong>Note:</strong> You should always register or unregister rules in bulk rather than +individually because each of these operations recreates internal data +structures. This re-creation is computationally expensive but facilitates a +very fast URL matching algorithm for hundreds of thousands of URLs. +</p> + + +<h2 id="evaluation">Evaluation of conditions and actions</h2> + +<p> +The Declarative Web Request API follows the +<a href="webRequest.html#life_cycle">Life cycle model for web requests</a> of +the <a href="webRequest.html">Web Request API</a>. This means that conditions +can only be tested at specific stages of a web request and, likewise, actions +can also only be executed at specific stages. The following tables list the +request stages that are compatible with conditions and actions. +</p> + +<p> +<table> + <tr> + <th colspan="5">Request stages during which condition attributes can be processed. + </tr> + <tr> + <th>Condition attribute + <th>onBeforeRequest + <th>onBeforeSendHeaders + <th>onHeadersReceived + <th>onAuthRequired + </tr> + <tr><td>url<td>✓<td>✓<td>✓<td>✓ + <tr><td>resourceType<td>✓<td>✓<td>✓<td>✓ + <tr><td>contentType<td><td><td>✓<td> + <tr><td>excludeContentType<td><td><td>✓<td> + <tr><td>responseHeaders<td><td><td>✓<td> + <tr><td>excludeResponseHeaders<td><td><td>✓<td> + <tr> + <th colspan="5" style="padding-top:2em">Request stages during which actions can be executed. + </tr> + <tr> + <th>Event + <th>onBeforeRequest + <th>onBeforeSendHeaders + <th>onHeadersReceived + <th>onAuthRequired + </tr> + <tr><td>AddRequestCookie<td><td>✓<td><td> + <tr><td>AddResponseCookie<td><td><td>✓<td> + <tr><td>AddResponseHeader<td><td><td>✓<td> + <tr><td>CancelRequest<td>✓<td>✓<td>✓<td>✓ + <tr><td>EditRequestCookie<td><td>✓<td><td> + <tr><td>EditResponseCookie<td><td><td>✓<td> + <tr><td>IgnoreRules<td>✓<td>✓<td>✓<td>✓ + <tr><td>RedirectByRegEx<td>✓<td><td><td> + <tr><td>RedirectRequest<td>✓<td><td><td> + <tr><td>RedirectToEmptyDocument<td>✓<td><td><td> + <tr><td>RedirectToTransparentImage<td>✓<td><td><td> + <tr><td>RemoveRequestCookie<td><td>✓<td><td> + <tr><td>RemoveRequestHeader<td><td>✓<td><td> + <tr><td>RemoveResponseCookie<td><td><td>✓<td> + <tr><td>RemoveResponseHeader<td><td><td>✓<td> + <tr><td>SetRequestHeader<td><td>✓<td><td> +</table> +</p> + +<p> +<strong>Example:</strong> It is possible to combine a +<code>new chrome.declarativeWebRequest.RequestMatcher({contentType: ["image/jpeg"]})</code> +condition with a <code>new chrome.declarativeWebRequest.CancelRequest()</code> +action because both of them can be evaluated in the onHeadersReceived stage. +It is, however, impossible to combine the request matcher with a +<code>new chrome.declarativeWebRequest.RedirectToTransparentImage()</code> +because redirects cannot be executed any more by the time the content +type has been determined. +</p> + +<h2 id="precedences">Using priorities to override rules</h2> + +<p> +Rules can be associated with priorities as described in the +<a href="events.html#declarative">Events API</a>. This mechanism can be used +to express exceptions. The following example will block all requests to +images named "evil.jpg" except on the server "myserver.com". +</p> + +<pre> +var rule1 = { + priority: 100, + conditions: [ + new chrome.declarativeWebRequest.RequestMatcher({ + url: { pathEquals: 'evil.jpg' } }) + ], + actions: [ + new chrome.declarativeWebRequest.CancelRequest() + ] +}; +var rule2 = { + priority: 1000, + conditions: [ + new chrome.declarativeWebRequest.RequestMatcher({ + url: { hostSuffix: '.myserver.com' } }) + ], + actions: [ + new chrome.declarativeWebRequest.IgnoreRules({ + lowerPriorityThan: 1000 }) + ] +}; +chrome.declarativeWebRequest.onRequest.addRules([rule1, rule2]); +</pre> + +<p> +It is important to recognize that the <code>IgnoreRules</code> action is not +persisted across <a href="#evaluation">request stages</a>. All conditions of +all rules are evaluated at each stage of a web request. If an +<code>IgnoreRules</code> action is executed, it applies only to other actions +that are executed for the same web request in the same stage. +</p> diff --git a/chrome/common/extensions/docs/templates/intros/devtools_inspectedWindow.html b/chrome/common/extensions/docs/templates/intros/devtools_inspectedWindow.html new file mode 100644 index 0000000..13cfffb --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/devtools_inspectedWindow.html @@ -0,0 +1,97 @@ +<p> +Use <code>chrome.devtools.inspectedWindow</code> +to interact with the inspected window: +obtain the tab ID for the inspected page, +evaluate the code in the context of inspected window, +reload the page, +or obtain the list of resources within the page. +</p><p> +See <a href="devtools.html">DevTools APIs summary</a> for +general introduction to using Developer Tools APIs. +</p> + +<h2>Overview</h2> +<p> +The <a href="#property-tabId"><code>tabId</code></a> property +provides the tab identifier that you can use with the +<a href="tabs.html"><code>chrome.tabs.*</code></a> API calls. +However, please note that <code>chrome.tabs.*</code> API is not +exposed to the Developer Tools extension pages due to security considerations +— you will need to pass the tab ID to the background page and invoke +the <code>chrome.tabs.*</code> API functions from there. +</p> +<p> +The <code>eval()</code> method provides the ability for extensions to execute +JavaScript code in the context of the main frame of the inspected page. +This method is powerful when used in the right context +and dangerous when used inappropriately. +Use the <code>chrome.tabs.executeScript()</code> method +unless you need the specific functionality +that the <code>eval()</code> method provides. +</p> +<p>Here are the main differences between the +<code>eval()</code> and <code>chrome.tabs.executeScript()</code> methods: +</p><ul> +<li>The <code>eval()</code> method does not +use an isolated world for the code being evaluated, so the JavaScript state +of the inspected window is accessible to the code. +Use this method when access to the JavaScript state of the inspected page +is required. +</li><li> +The execution context of the code being evaluated includes the +<a href="http://code.google.com/chrome/devtools/docs/console.html">Developer +Tools console API</a>. +For example, +the code can use <code>inspect()</code> and <code>$0</code>. +</li><li> +The evaluated code may return a value that is passed to the extension callback. +The returned value has to be a valid JSON object (it may contain only +primitive JavaScript types and acyclic references to other JSON +objects). + +<em>Please observe extra care while processing the data received from the +inspected page — the execution context is essentially controlled by the +inspected page; a malicious page may affect the data being returned to the +extension.</em> +</li></ul> +<p class="caution"> +<strong>Important:</strong> +Due to the security considerations explained above, the +<a href="tabs.html#method-executeScript"><code +>chrome.tabs.executeScript()</code></a> method is the preferred way for an +extension to access DOM data of the inspected page in cases where the access to +JavaScript state of the inspected page is not required.</em> +</p><p> +The <code>reload()</code> method may be used to reload the inspected page. +Additionally, the caller can specify an override for the user agent string, +a script that will be injected early upon page load, and an option to force +reload of cached resources. +</p><p> +Use the <code>getResources()</code> call and the <code>onResourceContent</code> +event to obtain the list of resources (documents, stylesheets, scripts, images +etc) within the inspected page. The <code>getContent()</code> and <code +>setContent()</code> methods of the <code>Resource</code> class along with the +<code>onResourceContentCommitted</code> event may be used to support +modification of the resource content, for example, by an external editor. +</p> + +<h2 id="overview-examples">Examples</h2> +<p>The following code checks for the version of jQuery used by the inspected +page: + +<pre> +chrome.devtools.inspectedWindow.eval( + "jQuery.fn.jquery", + function(result, isException) { + if (isException) + console.log("the page is not using jQuery"); + else + console.log("The page is using jQuery v" + result); + } +); +</pre> + +<p> +You can find more examples that use Developer Tools APIs in +<a href="samples.html#devtools">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/devtools_network.html b/chrome/common/extensions/docs/templates/intros/devtools_network.html new file mode 100644 index 0000000..7af3fdf --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/devtools_network.html @@ -0,0 +1,53 @@ +<p id="classSummary"> +Use the <code>chrome.devtools.network</code> module to retrieve +the information about network requests displayed by the Developer Tools +in the Network panel. +</p><p> +See <a href="devtools.html">DevTools APIs summary</a> for +general introduction to using Developer Tools APIs</a>. +</p> + +<h2>Overview</h2> + +<p> +Network requests information is represented in the HTTP Archive format +(<em>HAR</em>). The description of HAR is outside of scope of this document, +please refer to <a href= +"http://www.softwareishard.com/blog/har-12-spec/"> +HAR v1.2 Specification</a>. +</p><p> +In terms of HAR, the +<code>chrome.devtools.network.getHAR()</code> method returns +entire <em>HAR log</em>, while +<code>chrome.devtools.network.onRequestFinished</code> event +provides <em>HAR entry</em> as an argument to the event callback. +</p> +<p>Note that request content is not provided as part of HAR for efficieny +reasons. You may call request's <code>getContent()</code> method to retrieve +content. +<p>If the Developer Tools window is opened after the page is loaded, +some requests may be missing +in the array of entries returned by <code>getHAR()</code>. +Reload the page to get all requests. +In general, the list of +requests returned by <code>getHAR()</code> should match that displayed in +the Network panel. +<h2 id="overview-examples">Examples</h2> + +<p>The following code logs URLs of all images larger than 40KB as they are +loaded:</p> + +<pre> +chrome.devtools.network.onRequestFinished.addListener( + function(request) { + if (request.response.bodySize > 40*1024) + chrome.experimental.devtools.console.addMessage( + chrome.experimental.devtools.console.Severity.Warning, + "Large image: " + request.request.url); +}); +</pre> + +<p> +You can find more examples that use this API in +<a href="samples.html#devtools.network">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/devtools_panels.html b/chrome/common/extensions/docs/templates/intros/devtools_panels.html new file mode 100644 index 0000000..56cfe57 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/devtools_panels.html @@ -0,0 +1,64 @@ +<p id="classSummary"> +Use the <code>chrome.devtools.panels</code> module to integrate +your extension into Developer Tools window UI: create your own panels, access +existing panels, and add sidebars. +</p><p> +See <a href="devtools.html">DevTools APIs summary</a> for +general introduction to using Developer Tools APIs. +</p> + +<h2>Overview</h2> + +<p> +Each extension panel and sidebar is displayed as a separate HTML page. All +extension pages displayed in the Developer Tools window have access to all +modules in <code>chrome.devtools</code> API, as well as to +<a href="extension.html">chrome.extension</a> API. Other extension APIs are not +available to the pages within Developer Tools window, but you may invoke them +by sending a request to the background page of your extension, similarly to how +it's done in the <a href="overview.html#contentScripts">content scripts</a>. +</p><p> +You can use the <code><a href="#method-setOpenResourceHandler" +>setOpenResourceHandler()</a></code> method to install a +callback function that handles user requests to open a resource (typically, +a click on a resource link in the Developer Tools window). At most one of the +installed handlers gets called; users can specify (using the Developer Tools +Settings dialog) either the default behavior or an extension to handle resource +open requests. If an extension calls <code>setOpenResourceHandler()</code> +multiple times, only the last handler is retained. +</p> +<h2 id="overview-examples">Examples</h2> +<p>The following code adds a panel contained in <code>Panel.html</code>, +represented by <code>FontPicker.png</code> on the Developer Tools toolbar +and labeled as <em>Font Picker</em>:</p> + +<pre> +chrome.devtools.panels.create("Font Picker", + "FontPicker.png", + "Panel.html" + function(panel) { ... }); +</pre> +<p>The following code adds a sidebar pane contained in +<code>Sidebar.html</code> and titled <em>Font Properties</em> to the Elements +panel, then sets its height to <code>8ex</code>: +<pre> +chrome.devtools.panels.elements.createSidebarPane("Font Properties", + function(sidebar) { + sidebar.setPage("Sidebar.html"); + sidebar.setHeight("8ex"); + }); +</pre> +<p> +This screenshot demonstrates the effect the above examples would have on +Developer Tools window: + +<img src="{{static}}/images/devtools-panels.png" + style="margin-left: 20px" + width="686" height="289" + alt="Extension icon panel on DevTools toolbar" /> +</p> + +<p> +You can find examples that use this API in +<a href="samples.html#Chrome Query">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/downloads.html b/chrome/common/extensions/docs/templates/intros/downloads.html new file mode 100644 index 0000000..ee107d1 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/downloads.html @@ -0,0 +1,33 @@ +<p>The downloads API allows you to programmatically initiate, monitor, +manipulate, and search for downloads.</p> + +<h2 id='manifest'>Manifest</h2> + +<p> You must declare the 'downloads' permission in the <a +href='manifest.html'>extension manifest</a> to use this API, along with <a +href='manifest.html#permissions'>host permissions</a> for any hosts that you +may pass to <a href='#method-download'>download()</a>.</p> + +<pre>{ + 'name': 'My extension', + ... +<b> 'permissions': [ + 'downloads', + '*://*.google.com' + ]</b>, + ... +}</pre> + +<p>If the URL's hostname is not specified in the permissions, then <a +href='#method-download'>download()</a> will call its callback with a null +<code>downloadId</code> and set the <a +href='extension.html#property-lastError'>chrome.extensions.lastError</a> +object to indicate that the extension does not have permission to access that +hostname.</p> + +<h2 id='examples'>Examples</h2> + +<p>You can find simple examples of using the downloads module in the <a +href='http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/downloads/'>examples/api/downloads</a> +directory. For other examples and for help in viewing the source code, see <a +href='samples.html'>Samples</a>.</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/events.html b/chrome/common/extensions/docs/templates/intros/events.html new file mode 100644 index 0000000..d40e231 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/events.html @@ -0,0 +1,212 @@ +<p> +An <code>Event</code> is an object +that allows you to be notified +when something interesting happens. +Here's an example of using the +<code>chrome.tabs.onCreated</code> event +to be notified whenever there's a new tab: +</p> + +<pre> +chrome.tabs.onCreated.<b>addListener(function(</b>tab<b>) {</b> + appendToLog('tabs.onCreated --' + + ' window: ' + tab.windowId + + ' tab: ' + tab.id + + ' index: ' + tab.index + + ' url: ' + tab.url); +<b>});</b> +</pre> + +<p> +As the example shows, +you register for notification using <code>addListener()</code>. +The argument to <code>addListener()</code> +is always a function that you define to handle the event, +but the parameters to the function depend on +which event you're handling. +Checking the documentation for +<a href="tabs.html#event-onCreated"><code>chrome.tabs.onCreated</code></a>, +you can see that the function has a single parameter: +a <a href="tabs.html#type-Tab">Tab</a> object +that has details about the newly created tab. +</p> + + +{{^is_apps}} +<div class="doc-family extensions"> +<h2 id="declarative">Declarative Event Handlers</h2> + +<p> +The declarative event handlers provide a means to define rules consisting of +declarative conditions and actions. Conditions are evaluated in the browser +rather than the JavaScript engine which reduces roundtrip latencies and allows +for very high efficiency. +</p> + +<p>Declarative event handlers are used for example in the <a + href="declarativeWebRequest.html">Declarative Web Request API</a> and possibly +further extension APIs in the future. This page describes the underlying +concepts of all declarative event handlers. +</p> + +<h3 id="rules">Rules</h3> + +<p>The simplest possible rule consists of one or more conditions and one or more +actions:</p> +<pre> +var rule = { + conditions: [ /* my conditions */ ], + actions: [ /* my actions */ ] +}; +</pre> + +<p>If any of the conditions is fulfilled, all actions are executed.</p> + +<p>In addition to conditions and actions you may give each rule an identifier, +which simplifies unregistering previously registered rules, and a priority to +define precedences among rules. Priorities are only considered if rules conflict +each other or need to be executed in a specific order. Actions are executed in +decendending order of the priority of their rules.</p> + +<pre> +var rule = { + id: "my rule", // optional, will be generated if not set. + priority: 100, // optional, defaults to 100. + conditions: [ /* my conditions */ ], + actions: [ /* my actions */ ] +}; +</pre> + +<h3 id="eventobjects">Event objects</h3> + +<p> +<a href="events.html">Event objects</a> may support rules. These event objects +don't call a callback function when events happen but test whether any +registered rule has at least one fulfilled condition and execute the actions +associated with this rule. Event objects supporting the declarative API have +three relevant methods: <a href="#method-addRules"><code>addRules()</code></a>, +<a href="#method-removeRules"><code>removeRules()</code></a>, and +<a href="#method-getRules"><code>getRules()</code></a>. +</p> + +<h3 id="addingrules">Adding rules</h3> + +<p> +To add rules call the <code>addRules()</code> function of the event object. It +takes an array of rule instances as its first parameter and a callback function +that is called on completion. +</p> + +<pre> +var rule_list = [rule1, rule2, ...]; +function addRules(rule_list, function callback(details) {...}); +</pre> + +<p> +If the rules were inserted successfully, the <code>details</code> parameter +contains an array of inserted rules appearing in the same order as in the passed +<code>rule_list</code> where the optional parameters <code>id</code> and +<code>priority</code> were filled with the generated values. If any rule is +invalid, e.g., because it contained an invalid condition or action, none of the +rules are added and the <a + href="extension.html#property-lastError">lastError</a> variable is set when +the callback function is called. Each rule in <code>rule_list</code> must +contain a unique identifier that is not currently used by another rule or an +empty identifier. +</p> + +<p class="note"> +<strong>Note:</strong> Rules are persistent across browsing sessions. Therefore, +you should install rules during extension installation time using the +<code><a href="runtime.html#event-onInstalled">chrome.runtime.onInstalled</a></code> +event. Note that this event is also triggered when an extension is updated. +Therefore, you should first clear previously installed rules and then register +new rules. +</p> + +<h3 id="removingrules">Removing rules</h3> + +<p> +To remove rules call the <code>removeRules()</code> function. It accepts an +optional array of rule identifiers as its first parameter and a callback +function as its second parameter. +</p> + +<pre> +var rule_ids = ["id1", "id2", ...]; +function removeRules(rule_ids, function callback() {...}); +</pre> + +<p> +If <code>rule_ids</code> is an array of identifiers, all rules having +identifiers listed in the array are removed. If <code>rule_ids</code> lists an +identifier, that is unknown, this identifier is silently ignored. If +<code>rule_ids</code> is <code>undefined</code>, all registered rules of this +extension are removed. The <code>callback()</code> function is called when the +rules were removed. +</p> + +<h3 id="retrievingrules">Retrieving rules</h3> + +<p> +To retrieve a list of currently registered rules, call the +<code>getRules()</code> function. It accepts an optional array of rule +identifiers with the same semantics as <code>removeRules</code> and a callback +function. +</p> + +<pre> +var rule_ids = ["id1", "id2", ...]; +function getRules(rule_ids, function callback(details) {...}); +</pre> + +<p> +The <code>details</code> parameter passed to the <code>calback()</code> function +refers to an array of rules including filled optional parameters. +</p> +</div> +{{/is_apps}} + +{{^is_apps}} +<div class="doc-family extensions"> +<h2 id="filtered">Filtered events</h2> + +<p>Filtered events are a mechanism that allows listeners to specify a subset of +events that they are interested in. A listener that makes use of a filter won't +be invoked for events that don't pass the filter, which makes the listening +code more declarative and efficient - an <a href="event_pages.html">event + page</a> page need not be woken up to handle events it doesn't care +about.</p> + +<p>Filtered events are intended to allow a transition from manual filtering +code like this:</p> + +<pre> +chrome.webNavigation.onCommitted.addListener(function(e) { + if (hasHostSuffix(e.url, 'google.com') || + hasHostSuffix(e.url, 'google.com.au')) { + // ... + } +}); +</pre> + +<p>into this:</p> + +<pre> +chrome.webNavigation.onCommitted.addListener(function(e) { + // ... +}, {url: [{hostSuffix: 'google.com'}, + {hostSuffix: 'google.com.au'}]}); +</pre> + +<p>Events support specific filters that are meaningful to that event. The list +of filters that an event supports will be listed in the documentation for that +event in the "filters" section.</p> + +<p>When matching URLs (as in the example above), event filters support the same +URL matching capabilities as expressable with a <a + href="events.html#type-UrlFilter">UrlFilter</a>, except for scheme and port +matching.</p> + +</div> +{{/is_apps}} diff --git a/chrome/common/extensions/docs/templates/intros/experimental_app.html b/chrome/common/extensions/docs/templates/intros/experimental_app.html new file mode 100644 index 0000000..458c28c --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/experimental_app.html @@ -0,0 +1 @@ +<p>The current methods allow applications to generate passive notifications.</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/experimental_devtools_audits.html b/chrome/common/extensions/docs/templates/intros/experimental_devtools_audits.html new file mode 100644 index 0000000..ac2fa99 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/experimental_devtools_audits.html @@ -0,0 +1,72 @@ +<p id="classSummary"> +Use the <code>chrome.experimental.devtools.audits</code> module to add new audit +categories to Developer Tools' Audit panel. +</p><p> +See <a href="experimental.devtools.html">DevTools APIs summary</a> for +general introduction to using Developer Tools APIs</a>. +</p> + +<h2>Overview</h2> + +<p> +Each audit category is represented by a line on <em>Select audits to run</em> +screen in the Audits panel. The following example adds a category named +<em>Readability</em>:</p> +<pre> +var category = chrome.experimental.devtools.audits.addCategory("Readability", 2); +</pre> +<img src="{{static}}/images/devtools-audits-category.png" + style="margin-left: 20px" + width="489" height="342" + alt="Extension audit category on the launch screen of Audits panel" /> +<p> +If the category's checkbox is checked, the <code>onAuditStarted</code> event of +that category will be fired when user clicks the <em>Run</em> button. +</p> +<p>The event handler in your extension receives <code>AuditResults</code> +as an argument and should add one or more results using <code>addResult()</code> +method. This may be done asynchronously, i.e. after the handler returns. The +run of the category is considered to be complete once the extension adds the +number of results declared when adding the category with +<code>addCategory()</code> or +calls AuditResult's <code>done()</code> method. +</p> +<p>The results may include additional details visualized as an expandable +tree by the Audits panel. You may build the details tree using the +<code>createResult()</code> and <code>addChild()</code> methods. The child node +may include specially formatted fragments created by the +<code>auditResults.createSnippet()</code> +and <code>auditResults.createURL()</code> methods. +</p> + +<h2>Examples</h2> +<p>The following example adds a handler for onAuditStarted event that creates +two audit results and populates one of them with the additional details: +</p> + +<pre> +category.onAuditStarted.addListener(function(results) { + var details = results.createResult("Details..."); + var styles = details.addChild("2 styles with small font"); + var elements = details.addChild("3 elements with small font"); + + results.addResult("Font Size (5)", + "5 elements use font size below 10pt", + results.Severity.Severe, + details); + results.addResult("Contrast", + "Text should stand out from background", + results.Severity.Info); +}); +</pre> +<p>The audit result tree produced by the snippet above will look like this: +</p> +<img src="{{static}}/images/devtools-audits-results.png" + style="margin-left: 20px" + width="330" height="169" + alt="Audit results example" /> + +<p> +You can find more examples that use this API in +<a href="samples.html#devtools.audits">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/experimental_devtools_console.html b/chrome/common/extensions/docs/templates/intros/experimental_devtools_console.html new file mode 100644 index 0000000..cc9b81a --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/experimental_devtools_console.html @@ -0,0 +1,7 @@ +<p> +Use <code>chrome.experimental.devtools.console</code> to retrieve messages from +the inspected page console and post messages there. <code>getMessages()</code> +returns the list of messages on the console, <code>onMessageAdded</code> +event provides notifications on new messages, and <code>addMessage()</code> +allows an extension to add new messages. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/experimental_discovery.html b/chrome/common/extensions/docs/templates/intros/experimental_discovery.html new file mode 100644 index 0000000..288bac5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/experimental_discovery.html @@ -0,0 +1 @@ +<p>The current methods allow extensions to inject suggested links in the recommended pane of the New Tab Page.</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/experimental_infobars.html b/chrome/common/extensions/docs/templates/intros/experimental_infobars.html new file mode 100644 index 0000000..d3d0476 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/experimental_infobars.html @@ -0,0 +1,48 @@ +<p> +The infobars API allows you to add a +horizontal panel just above a tab's contents, +as the following screenshot shows. +</p> + +<p> +<img src="{{static}}/images/infobar.png" + width="566" height="150" + alt="An infobar asking whether the user wants to translate the current page" /> +</p> + +<p> +Use an infobar to tell the reader +something about a particular page. +When the user leaves the page for which the infobar is displayed, +Google Chrome automatically closes the infobar. +</p> + +<p> +You implement the content of your +infobar using HTML. Because infobars are ordinary pages inside an extension, +they can +<a href="overview.html#pageComm">communicate with other extension pages</a>. +</p> + + +<h2 id="manifest">Manifest</h2> + +<p> +The infobars API is currently +experimental, so you must declare the "experimental" +permission to use it. Also, you should specify +a 16x16-pixel icon for display next to your infobar. +For example: +</p> + +<pre>{ + "name": "Andy's infobar extension", + "version": "1.0", + <b>"permissions": ["experimental"],</b> + <b>"icons": {</b> + <b>"16": "16.png"</b> + <b>},</b> + "background": { + "scripts": ["background.js"] + } +}</pre>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/experimental_speechInput.html b/chrome/common/extensions/docs/templates/intros/experimental_speechInput.html new file mode 100644 index 0000000..af6b8e9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/experimental_speechInput.html @@ -0,0 +1,109 @@ +<p id="classSummary"> +The <code>chrome.experimental.speechInput</code> module provides +one-shot speech recognition to Chrome extensions. +This module is still experimental. For information on how to use experimental +APIs, see the <a href="experimental.html">chrome.experimental.* APIs</a> page. +</p> + +<h2 id="manifest">Manifest</h2> +<p>You must declare the "experimental" permission in the <a + href="manifest.html">extension manifest</a> to use the speech input +API. +For example:</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "experimental" + ]</b>, + ... +}</pre> + +<h2 id="howToStart">How to start speech recognition</h2> +<p>To start recognizing speech an extension must call the <code>start()</code> +method. If provided, your callback will be called once recording has +successfully started. In case of error <code>chrome.extension.lastError</code> +will be set.</p> + +<p>This API provides exclusive access to the default recording device to the +first extension requesting it. Consequently, any calls to <code>start()</code> +when the device is being used by another extension or web page will fail and set +<code>chrome.extension.lastError</code>. The message <code>requestDenied</code> +will be set if another extension in the same profile is making use of the API. +Otherwise <code>noRecordingDeviceFound</code>, <code>recordingDeviceInUse</code> +or <code>unableToStart</code> will be set depending on the situation.</p> + +<p>To check whether recording is currently active, call the +<code>isRecording()</code> method. Please note that it only checks for audio +recording within Chrome.</p> + + +<h2 id="howToGetResults">How to get speech recognition results</h2> +<p>Listen to the <code>onResult</code> event to receive speech recognition +results.</p> + +<pre> +var callback = function(result) { ... }; + +chrome.experimental.speechInput.onResult.addListener(callback); +</pre> + +<p>The <code>result</code> object contains an array of +<a href="#type-SpeechInputResultHypothesis">SpeechInputResultHypothesis</a> +sorted by decreasing likelihood.</p> + +<p>Recording automatically stops when results are received. It is safe to call +<code>start()</code> again from the results callback.</p> + +<p>To handle errors during speech recognition listen for the +<code>onError</code> event.</p> + +<pre> +var callback = function(error) { ... }; + +chrome.experimental.speechInput.onError.addListener(callback); +</pre> + +</p>Recording will automatically stop in case of error. +It is safe to call <code>start()</code> again from the error callback.</p> + + +<h2 id="howToStop">How to stop recording</h2> +<p>To stop speech recognition call the <code>stop()</code> method. If provided, +the callback function will be called once recording has successfully stopped. +In case of error <code>chrome.extension.lastError</code> will be set. +</p> + + +<h2 id="otherFeatures">Other features</h2> +<ul><li> +<code>onSoundStart</code> - Event generated when start of sound is detected +(from previously being silent). +</li><li> +<code>onSoundEnd</code> - Event generated when end of sound is detected (a +continued period of silence). +</li></ul> + + +<h2 id="examples">Examples</h2> +<p>The following example illustrates how to show a JavaScript alert with the +most likely recognition result.</p> +<pre> +function checkStart() { + if (chrome.extension.lastError) { + alert("Couldn't start speech input: " + chrome.extension.lastError.message); + } +} + +function recognitionFailed(error) { + alert("Speech input failed: " + error.code); +} + +function recognitionSucceeded(result) { + alert("Recognized '" + result.hypotheses[0].utterance + "' with confidence " + result.hypotheses[0].confidence); +} + +chrome.experimental.speechInput.onError.addListener(recognitionFailed); +chrome.experimental.speechInput.onResult.addListener(recognitionSucceeded); +chrome.experimental.speechInput.start({ "language": "en" }, checkStart); +</pre>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/extension.html b/chrome/common/extensions/docs/templates/intros/extension.html new file mode 100644 index 0000000..2ab3f08 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/extension.html @@ -0,0 +1,44 @@ +<p id="classSummary"> +The <code>chrome.extension</code> module +has utilities that can be used by any extension page. +It includes support for exchanging messages +between an extension and its content scripts +or between extensions, +as described in detail in +<a href="messaging.html">Message Passing</a>. +</p> + +<h2 id="content scripts">Support for content scripts</h2> +<p> +Unlike the other chrome.* APIs, +parts of <code>chrome.extension</code> +can be used by content scripts: +</p> + +<dl> + <dt> + <a href="#method-sendMessage"><code>sendMessage()</code></a> and + <a href="#event-onMessage"><code>onMessage</code></a> + </dt> + <dd> + Simple communication with extension pages + </dd> + <dt> + <a href="#method-connect"><code>connect()</code></a> and + <a href="#event-onConnect"><code>onConnect</code></a> + </dt> + <dd> + Extended communication with extension pages + </dd> + <dt> + <a href="#method-getURL"><code>getURL()</code></a> + </dt> + <dd> + Access to extension resources such as image files + </dd> +</dl> + +<p> +For details, see +<a href="content_scripts.html">Content Scripts</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/fileBrowserHandler.html b/chrome/common/extensions/docs/templates/intros/fileBrowserHandler.html new file mode 100644 index 0000000..40d681a --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/fileBrowserHandler.html @@ -0,0 +1,154 @@ +<p id="classSummary"> +Use the <code>chrome.fileBrowserHandler</code> module to +extend the Chrome OS file browser. +For example, you can use this API +to enable users to upload files to your website. +</p> + +<p class="caution"> +<b>Important:</b> +This API works <b>only on Chrome OS</b>. +</p> + +<p> +The Chrome OS file browser comes up when +the user either presses Ctrl+M +or connects an external storage device, +such as an SD card, USB key, external drive, or digital camera. +Besides showing the files on external devices, +the file browser can also display files +that the user has previously saved to the system. +</p> + +<p> +When the user selects one or more files, +the file browser adds buttons +representing the valid handlers for those files. +For example, in the following screenshot, +selecting a file with a ".jpg" suffix +results in an "Upload to Picasa" button that the user can click. +</p> + +<p> +<img src="{{static}}/images/filebrowserhandler.png" + width="640" height="400" alt="file browser screenshot" /> +</p> + + +<h2 id="manifest">Manifest</h2> + +<p> +You must declare the "fileBrowserHandler" permission +in the <a href="manifest.html">extension manifest</a>, +and you must use the "file_browser_handlers" field +to register the extension as a handler of at least one file type. +You should also provide a 16x16 icon +to be displayed on the button. +For example: +</p> + +<pre> +{ + "name": "My extension", + ... + <b>"file_browser_handlers"</b>: [ + { + <b>"id"</b>: "upload", + <b>"default_title"</b>: "Save to Gallery", <em>// What the button will display</em> + <b>"file_filters"</b>: [ + "filesystem:*.jpg", <em>// To match all files, use "filesystem:*.*"</em> + "filesystem:*.jpeg", + "filesystem:*.png" + ] + } + ]</b>, + "permissions" : [ + <b>"fileBrowserHandler"</b> + ], + "icons": { <b>"16"</b>: "icon16.png", + "48": "icon48.png", + "128": "icon128.png" }, + ... +}</pre> + +<p class="note"> +<b>Note:</b> +You can specify locale-specific strings for the value of "default_title". +See <a href="i18n.html">Internationalization (i18n)</a> for details. +</p> + +<h2 id="code">Implementing a file browser handler</h2> + +<p> +To use this API, +you must implement a function that handles the <code>onExecute</code> event +of <code>chrome.fileBrowserHandler</code>. +Your function will be called whenever the user clicks the button +that represents your file browser handler. +In your function, use the HTML5 +<a href="http://www.html5rocks.com/tutorials/file/filesystem/">FileSystem API</a> +to get access to the file contents. +Here is an example: +</p> + +<pre> +<em>//In background.html:</em> +chrome.fileBrowserHandler.onExecute.addListener(function(id, details) { + if (id == 'upload') { + var fileEntries = details.entries; + for (var i = 0, entry; entry = fileEntries[i]; ++i) { + entry.file(function(file) { + <em>// send file somewhere</em> + }); + } + } +}); +</pre> + +<p> +Your event handler is passed two arguments: +</p> + +<dl> + <dt> id </dt> + <dd> The "id" value from the manifest file. + If your extension implements multiple handlers, + you can check the <code>id</code> value + to see which handler has been triggered. + </dd> + <dt> details </dt> + <dd> An object describing the event. + You can get the file or files that the user has selected + from the <code>entries</code> field of this object, + which is an array of + FileSystem <code>Entry</code> objects. + </dd> +</p> + + +<!-- +<h2 id="manifest_details">Manifest details</h2> + +<p class="authornote"> +{PENDING: give details about "id" and "default_title". +It should be unique within your extension -- don't worry about other extensions. +"default_title" implies that you can change the title, +but you can't aside from internationalizing it. +</p> + +<p class="authornote"> +{PENDING: give details about the file_filters entry. +File filters are currently case-sensitive, but we plan to change that. +Mention <code>filesystem:*.*</code>. +</p> +--> + +<!-- +<h2 id="examples">Examples</h2> + +<p> +For examples of using this API, see ... +For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p> +-->
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/fontSettings.html b/chrome/common/extensions/docs/templates/intros/fontSettings.html new file mode 100644 index 0000000..1b16e63 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/fontSettings.html @@ -0,0 +1,56 @@ +<p>The Font Settings API allows you to manage Chrome's font settings.</p> + +<h2 id="manifest">Manifest</h2> +<p>To use the Font Settings API, you must declare the "fontSettings" permission +in the <a href="manifest.html">extension manifest</a>. +For example:</p> +<pre>{ + "name": "My Font Settings Extension", + "description": "Customize your fonts", + "version": "0.2", + "permissions": ["fontSettings"] +}</pre> + +<h2 id="scripts">Generic Font Families and Scripts</h2> +<p>Chrome allows for some font settings to depend on certain generic font +families and language scripts. For example, the font used for sans-serif +Simplified Chinese may be different than the font used for serif Japanese.</p> + +<p>The generic font families supported by Chrome are based on +<a href="http://www.w3.org/TR/CSS21/fonts.html#generic-font-families">CSS generic font families</a> +and are listed in the API reference below. When a webpage specifies a generic +font family, Chrome selects the font based on the corresponding setting. If no +generic font family is specified, Chrome uses the setting for the "standard" +generic font family.</p> + +<p>When a webpage specifies a language, Chrome selects the font based on the +setting for the corresponding language script. If no language is specified, +Chrome uses the setting for the default, or global, script.</p> + +<p>The supported language scripts are specified by ISO 15924 script code and +listed in the API reference below. Technically, Chrome settings are not strictly +per-script but also depend on language. For example, Chrome chooses the font for +Cyrillic (ISO 15924 script code "Cyrl") when a webpage specifies the Russian +language, and uses this font not just for Cyrillic script but for everything the +font covers, such as Latin.</p> + +<h2 id="examples">Examples</h2> +<p>The following code gets the standard font for Arabic.</p> +<pre> +chrome.fontSettings.getFont( + { genericFamily: 'standard', script: 'Arab' }, + function(details) { console.log(details.fontId); } +); +</pre> + +<p>The next snippet sets the sans-serif font for Japanese.</p> +<pre> +chrome.fontSettings.setFont( + { genericFamily: 'sansserif', script: 'Jpan', fontId: 'MS PGothic' } +); +</pre> + +<p>You can find a sample extension using the Font Settings API in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/fontSettings/">examples/api/fontSettings</a> +directory. For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>.</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/history.html b/chrome/common/extensions/docs/templates/intros/history.html new file mode 100644 index 0000000..9bac472 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/history.html @@ -0,0 +1,153 @@ +<p id="classSummary"> +Use the <code>chrome.history</code> module to interact with the +browser's record of visited pages. You can add, remove, and query +for URLs in the browser's history. +To override the history page with your own version, see +<a href="override.html">Override Pages</a>. +</p> + +<h2 id="manifest">Manifest</h2> + +<p>You must declare the "history" permission +in the <a href="manifest.html">extension manifest</a> +to use the history API. +For example:</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "history" + ]</b>, + ... +}</pre> + +<h2 id="transition_types">Transition types</h2> + +<p> +The history API uses a <em>transition type</em> to describe +how the browser navigated to a particular URL +on a particular visit. +For example, if a user visits a page +by clicking a link on another page, +the transition type is "link". +</p> + +<p> +The following table describes each transition type. +</p> + +<table> +<tr> + <th> Transition type </th> <th> Description </th> +</tr> +<tr id="tt_link"> + <td>"link"</td> + <td> + The user got to this page by clicking a link on another page. + </td> +</tr> +<tr id="tt_typed"> + <td>"typed"</td> + <td> + The user got this page by typing the URL in the address bar. + Also used for other explicit navigation actions. + See also <a href="#tt_generated">generated</a>, + which is used for cases where the user selected a choice + that didn't look at all like a URL. + </td> +</tr> +<tr id="tt_auto_bookmark"> + <td>"auto_bookmark"</td> + <td> + The user got to this page through a suggestion in the UI — + for example, through a menu item. + </td> +</tr> +<tr id="tt_auto_subframe"> + <td>"auto_subframe"</td> + <td> + Subframe navigation. + This is any content that is automatically + loaded in a non-top-level frame. + For example, if a page consists of + several frames containing ads, + those ad URLs have this transition type. + The user may not even realize the content in these pages + is a separate frame, and so may not care about the URL + (see also <a href="#tt_manual_subframe">manual_subframe</a>). + </td> +</tr> +<tr id="tt_manual_subframe"> + <td>"manual_subframe"</td> + <td> + For subframe navigations that are explicitly requested by the user + and generate new navigation entries in the back/forward list. + An explicitly requested frame is probably more important than + an automatically loaded frame + because the user probably cares about the fact that + the requested frame was loaded. + </td> +</tr> +<tr id="tt_generated"> + <td>"generated"</td> + <td> + The user got to this page by typing in the address bar + and selecting an entry that did not look like a URL. + For example, a match might have the URL of a Google search result page, + but it might appear to the user as "Search Google for ...". + These are not quite the same as <a href="#tt_typed">typed</a> navigations + because the user didn't type or see the destination URL. + See also <a href="#tt_keyword">keyword</a>. + </td> +</tr> +<tr id="tt_start_page"> + <td>"start_page"</td> + <td> + The page was specified in the command line or is the start page. + </td> +</tr> +<tr id="tt_form_submit"> + <td>"form_submit"</td> + <td> + The user filled out values in a form and submitted it. + Note that in some situations — + such as when a form uses script to submit contents — + submitting a form does not result in this transition type. + </td> +</tr> +<tr id="tt_reload"> + <td>"reload"</td> + <td> + The user reloaded the page, + either by clicking the reload button + or by pressing Enter in the address bar. + Session restore and Reopen closed tab use this transition type, too. + </td> +</tr> +<tr id="tt_keyword"> + <td>"keyword"</td> + <td> + The URL was generated from a replaceable keyword + other than the default search provider. + See also + <a href="#tt_keyword_generated">keyword_generated</a>. + </td> +</tr> +<tr id="tt_keyword_generated"> + <td>"keyword_generated"</td> + <td> + Corresponds to a visit generated for a keyword. + See also <a href="#tt_keyword">keyword</a>. + </td> +</tr> +</table> + +<h2 id="examples">Examples</h2> + +<p> +For examples of using this API, see the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/history/">history sample directory</a> and the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/test/data/extensions/api_test/history/">history API test directory</a>. +For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/i18n.html b/chrome/common/extensions/docs/templates/intros/i18n.html new file mode 100644 index 0000000..72fd10d --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/i18n.html @@ -0,0 +1,572 @@ +<!-- +[NOTEs for editors: + * Try to be consistent about string vs. message (it's probably not yet). +--> + + +<p id="classSummary"> +An <em>internationalized</em> extension +can be easily +<em>localized</em> — +adapted to languages and regions +that it didn't originally support. +</p> + +<p> +To internationalize your extension, +you need to put all of its user-visible strings into a file +named <a href="i18n-messages.html"><code>messages.json</code></a>. +Each time you localize your extension +you add a messages file +under a directory +named <code>_locales/<em>localeCode</em></code>, +where <em>localeCode</em> is a code such as +<code>en</code> for English. +</p> + +<p> +Here's the file hierarchy +for an internationalized extension that supports +English (<code>en</code>), +Spanish (<code>es</code>), and +Korean (<code>ko</code>): +</p> + +<img src="{{static}}/images/i18n-hierarchy.gif" + alt='In the extension directory: manifest.json, *.html, *.js, _locales directory. In the _locales directory: en, es, and ko directories, each with a messages.json file.' + width="385" height="77" /> + + +<h2 id="l10">How to support multiple languages</h2> + +<p> +Say you have an extension +with the files shown in the following figure: +</p> + +<img src="{{static}}/images/i18n-before.gif" + alt='A manifest.json file and a file with JavaScript. The .json file has "name": "Hello World". The JavaScript file has title = "Hello World";' + width="323" height="148"> + +<p> +To internationalize this extension, +you name each user-visible string +and put it into a messages file. +The extension's manifest, +CSS files, +and JavaScript code +use each string's name to get its localized version. +</p> + +<p> +Here's what the extension looks like when it's internationalized +(note that it still has only English strings): +</p> + +<img src="{{static}}/images/i18n-after-1.gif" + alt='In the manifest.json file, "Hello World" has been changed to "__MSG_extName__", and a new "default_locale" item has the value "en". In the JavaScript file, "Hello World" has been changed to chrome.i18n.getMessage("extName"). A new file named _locales/en/messages.json defines "extName".' + width="782" height="228"> + +<p class="note"> +<b>Important:</b> +If an extension has a <code>_locales</code> directory, +the <a href="manifest.html">manifest</a> +<b>must</b> define "default_locale". +</p> + +<p> +Some notes about internationalizing extensions: +</p> + +<ul> + <li><p> + You can use any of the <a href="#overview-locales">supported locales</a>. + If you use an unsupported locale, + Google Chrome ignores it. + </p></li> + + <li> + In <code>manifest.json</code> + and CSS files, + refer to a string named <em>messagename</em> like this: + <pre>__MSG_<em>messagename</em>__</pre> + </li> + + <li> + In your extension's JavaScript code, + refer to a string named <em>messagename</em> + like this: + <pre>chrome.i18n.getMessage("<em>messagename</em>")</pre> + + <li> <p> + In each call to <code>getMessage()</code>, + you can supply up to 9 strings + to be included in the message. + See <a href="#examples-getMessage">Examples: getMessage</a> + for details. + </p> + </li> + + <li><p> + Some messages, such as <code>@@bidi_dir</code> and <code>@@ui_locale</code>, + are provided by the internationalization system. + See the <a href="#overview-predefined">Predefined messages</a> section + for a full list of predefined message names. + </p> + </li> + + <li> + In <code>messages.json</code>, + each user-visible string has a name, a "message" item, + and an optional "description" item. + The name is a key + such as "extName" or "search_string" + that identifies the string. + The "message" specifies + the value of the string in this locale. + The optional "description" + provides help to translators, + who might not be able to see how the string is used in your extension. + For example: +<pre> +{ + "search_string": { + "message": "hello%20world", + "description": "The string we search for. Put %20 between words that go together." + }, + ... +}</pre> + +<p> +For more information, see +<a href="i18n-messages.html">Formats: Locale-Specific Messages</a>. +</p> + </li> +</ul> + +<p> +Once an extension is internationalized, +translating it is simple. +You copy <code>messages.json</code>, +translate it, +and put the copy into a new directory under <code>_locales</code>. +For example, to support Spanish, +just put a translated copy of <code>messages.json</code> +under <code>_locales/es</code>. +The following figure shows the previous extension +with a new Spanish translation. +</p> + +<img src="{{static}}/images/i18n-after-2.gif" + alt='This looks the same as the previous figure, but with a new file at _locales/es/messages.json that contains a Spanish translation of the messages.' + width="782" height="358"> + + +<h2 id="overview-predefined">Predefined messages</h2> + +<p> +The internationalization system provides a few predefined +messages to help you localize your extension. +These include <code>@@ui_locale</code>, +so you can detect the current UI locale, +and a few <code>@@bidi_...</code> messages +that let you detect the text direction. +The latter messages have similar names to constants in the +<a href="http://code.google.com/apis/gadgets/docs/i18n.html#BIDI"> +gadgets BIDI (bi-directional) API</a>. +</p> + +<p> +The special message <code>@@extension_id</code> +can be used in the CSS and JavaScript files of any extension, +whether or not the extension is localized. +This message doesn't work in manifest files. +</p> + +<p> +The following table describes each predefined message. +</p> + +<table> +<tr> + <th>Message name</th> <th>Description</th> +</tr> +<tr> + <td> <code>@@extension_id</code> </td> + <td>The extension ID; + you might use this string to construct URLs + for resources inside the extension. + Even unlocalized extensions can use this message. + <br> + <b>Note:</b> You can't use this message in a manifest file. + </td> +</tr> +<tr> + <td> <code>@@ui_locale</code> </td> + <td>The current locale; + you might use this string to construct locale-specific URLs. </td> +</tr> +<tr> + <td> <code>@@bidi_dir</code> </td> + <td> The text direction for the current locale, + either "ltr" for left-to-right languages such as English + or "rtl" for right-to-left languages such as Japanese. </td> +</tr> +<tr> + <td> <code>@@bidi_reversed_dir</code> </td> + <td> If the <code>@@bidi_dir</code> is "ltr", then this is "rtl"; + otherwise, it's "ltr". </td> +</tr> +<tr> + <td> <code>@@bidi_start_edge</code> </td> + <td> If the <code>@@bidi_dir</code> is "ltr", then this is "left"; + otherwise, it's "right". </td> +</tr> +<tr> + <td> <code>@@bidi_end_edge</code> </td> + <td> If the <code>@@bidi_dir</code> is "ltr", then this is "right"; + otherwise, it's "left". </td> +</tr> +</table> + +<p> +Here's an example of using <code>@@extension_id</code> in a CSS file +to construct a URL: +</p> + +<pre> +body { + <b>background-image:url('chrome-extension://__MSG_@@extension_id__/background.png');</b> +} +</pre> + +<p> +If the extension ID is abcdefghijklmnopqrstuvwxyzabcdef, +then the bold line in the previous code snippet becomes: +</p> + +<pre> +background-image:url('chrome-extension://abcdefghijklmnopqrstuvwxyzabcdef/background.png'); +</pre> + +<p> +Here's an example of using <code>@@bidi_*</code> messages in a CSS file: +</p> + +<pre> +body { + <b>direction: __MSG_@@bidi_dir__;</b> +} + +div#header { + margin-bottom: 1.05em; + overflow: hidden; + padding-bottom: 1.5em; + <b>padding-__MSG_@@bidi_start_edge__: 0;</b> + <b>padding-__MSG_@@bidi_end_edge__: 1.5em;</b> + position: relative; +} +</pre> + +<p> +For left-to-right languages such as English, +the bold lines become: +</p> + +<pre> +dir: ltr; +padding-left: 0; +padding-right: 1.5em; +</pre> + + +<h2 id="overview-locales">Locales</h2> + +<p> +You can choose from many locales, +including some (such as <code>en</code>) +that let a single translation support multiple variations of a language +(such as <code>en_GB</code> and <code>en_US</code>). +</p> + + +<h3 id="locales-supported">Supported locales</h3> + +<p> +Extensions can use any of the +<a href="http://code.google.com/chrome/webstore/docs/i18n.html#localeTable">locales that the Chrome Web Store supports</a>. +</p> + + +<h3 id="locales-usage">How extensions find strings</h3> + +<p> +You don't have to define every string for every locale +that your internationalized extension supports. +As long as the default locale's <code>messages.json</code> file +has a value for every string, +your extension will run no matter how sparse a translation is. +Here's how the extension system searches for a message: +</p> + +<ol> + <li> + Search the messages file (if any) + for the user's preferred locale. + For example, when Google Chrome's locale is set to + British English (<code>en_GB</code>), + the system first looks for the message in + <code>_locales/en_GB/messages.json</code>. + If that file exists and the message is there, + the system looks no further. + </li> + <li> + If the user's preferred locale has a region + (that is, the locale has an underscore: _), + search the locale without that region. + For example, if the <code>en_GB</code> messages file + doesn't exist or doesn't contain the message, + the system looks in the <code>en</code> messages file. + If that file exists and the message is there, + the system looks no further. + </li> + <li> + Search the messages file for the extension's default locale. + For example, if the extension's "default_locale" is set to "es", + and neither <code>_locales/en_GB/messages.json</code> + nor <code>_locales/en/messages.json</code> contains the message, + the extension uses the message from + <code>_locales/es/messages.json</code>. + </li> +</ol> + +<p> +In the following figure, +the message named "colores" is in all three locales +that the extension supports, +but "extName" is in only two of the locales. +Wherever a user running Google Chrome in US English sees the label "Colors", +a user of British English sees "Colours". +Both US English and British English users +see the extension name "Hello World". +Because the default language is Spanish, +users running Google Chrome in any non-English language +see the label "Colores" and the extension name "Hola mundo". +</p> + +<img src="{{static}}/images/i18n-strings.gif" + alt='Four files: manifest.json and three messages.json files (for es, en, and en_GB). The es and en files show entries for messages named "extName" and "colores"; the en_GB file has just one entry (for "colores").' + width="493" height="488" /> + +<h3 id="locales-testing">How to set your browser's locale</h3> + +<p> +To test translations, you might want to set your browser's locale. +This section tells you how to set the locale in +<a href="#testing-win">Windows</a>, +<a href="#testing-mac">Mac OS X</a>, and +<a href="#testing-linux">Linux</a>. +</p> + +<h4 id="testing-win">Windows</h4> + +<p> +You can change the locale using either +a locale-specific shortcut +or the Google Chrome UI. +The shortcut approach is quicker, once you've set it up, +and it lets you use several languages at once. +</p> + +<h5 id="win-shortcut">Using a locale-specific shortcut</h5> + +<p> +To create and use a shortcut that launches Google Chrome +with a particular locale: +</p> + +<ol> + <li> + Make a copy of the Google Chrome shortcut + that's already on your desktop. + </li> + <li> + Rename the new shortcut to match the new locale. + </li> + <li> + Change the shortcut's properties + so that the Target field specifies the + <code>--lang</code> and + <code>--user-data-dir</code> flags. + The target should look something like this: + +<pre><em>path_to_chrome.exe</em> --lang=<em>locale</em> --user-data-dir=c:\<em>locale_profile_dir</em></pre> + </li> + + <li> + Launch Google Chrome by double-clicking the shortcut. + </li> +</ol> + +<p> +For example, to create a shortcut +that launches Google Chrome in Spanish (<code>es</code>), +you might create a shortcut named <code>chrome-es</code> +that has the following target: +</p> + +<pre><em>path_to_chrome.exe</em> --lang=es --user-data-dir=c:\chrome-profile-es</pre> + +<p> +You can create as many shortcuts as you like, +making it easy to test your extension in multiple languages. +For example: +</p> + +<pre><em>path_to_chrome.exe</em> --lang=en --user-data-dir=c:\chrome-profile-en +<em>path_to_chrome.exe</em> --lang=en_GB --user-data-dir=c:\chrome-profile-en_GB +<em>path_to_chrome.exe</em> --lang=ko --user-data-dir=c:\chrome-profile-ko</pre> + +<p class="note"> +<b>Note:</b> +Specifying <code>--user-data-dir</code> is optional but handy. +Having one data directory per locale +lets you run the browser +in several languages at the same time. +A disadvantage is that because the locales' data isn't shared, +you have to install your extension multiple times — once per locale, +which can be challenging when you don't speak the language. +For more information, see +<a href="http://www.chromium.org/developers/creating-and-using-profiles">Creating and Using Profiles</a>. +</p> + + +<h5 id="win-ui">Using the UI</h5> + +<p> +Here's how to change the locale using the UI on Google Chrome for Windows: +</p> + +<ol> + <li> Wrench icon > <b>Options</b> </li> + <li> Choose the <b>Under the Hood</b> tab </li> + <li> Scroll down to <b>Web Content</b> </li> + <li> Click <b>Change font and language settings</b> </li> + <li> Choose the <b>Languages</b> tab </li> + <li> Use the drop down to set the <b>Google Chrome language</b> </li> + <li> Restart Chrome </li> +</ol> + + +<h4 id="testing-mac">Mac OS X</h4> + +<p> +To change the locale on Mac, +you use the system preferences. +</p> + +<ol> + <li> From the Apple menu, choose <b>System Preferences</b> </li> + <li> Under the <b>Personal</b> section, choose <b>International</b> </li> + <li> Choose your language and location </li> + <li> Restart Chrome </li> +</ol> + + +<h4 id="testing-linux">Linux</h4> + +<p> +To change the locale on Linux, +first quit Google Chrome. +Then, all in one line, +set the LANGUAGE environment variable +and launch Google Chrome. +For example: +</p> + +<pre> +LANGUAGE=es ./chrome +</pre> + + +<h2 id="overview-examples">Examples</h2> + +<p> +You can find simple examples of internationalization in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/i18n/">examples/api/i18n</a> +directory. +For a complete example, see +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/extensions/news/">examples/extensions/news</a>. +For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p> + + +<h3 id="examples-getMessage">Examples: getMessage</h3> + +<!-- +[PENDING: improve this section. it should probably start with a +one-variable example that includes the messages.json code.] +--> + +<p> +The following code gets a localized message from the browser +and displays it as a string. +It replaces two placeholders within the message with the strings +"string1" and "string2". +</p> + +<pre> +function getMessage() { + var message = chrome.i18n.getMessage("click_here", ["string1", "string2"]); + document.getElementById("languageSpan").innerHTML = message; +} +</pre> + +<p> +Here's how you'd supply and use a single string: +</p> + +<pre> +<em>// In JavaScript code</em> +status.innerText = chrome.i18n.getMessage("error", errorDetails); + +<em>// In messages.json</em> +"error": { + "message": "Error: $details$", + "description": "Generic error template. Expects error parameter to be passed in.", + "placeholders": { + "details": { + "content": "$1", + "example": "Failed to fetch RSS feed." + } + } +} +</pre> + +<p> +For more information about placeholders, see the +<a href="i18n-messages.html">Locale-Specific Messages</a> page. +For details on calling <code>getMessage()</code>, see the +<a href="#method-getMessage">API reference</a>. +</p> + +<h3 id="example-accept-languages">Example: getAcceptLanguages</h3> +<p> +The following code gets accept-languages from the browser and displays them as a +string by separating each accept-language with ','. +</p> + +<pre> +function getAcceptLanguages() { + chrome.i18n.getAcceptLanguages(function(languageList) { + var languages = languageList.join(","); + document.getElementById("languageSpan").innerHTML = languages; + }) +} +</pre> + +<p> +For details on calling <code>getAcceptLanguages()</code>, see the +<a href="#method-getAcceptLanguages">API reference</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/idle.html b/chrome/common/extensions/docs/templates/intros/idle.html new file mode 100644 index 0000000..0eedf22 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/idle.html @@ -0,0 +1,13 @@ +<h2 id="manifest">Manifest</h2> +<p>You must declare the "idle" permission in your extension's manifest to use the idle API. +For example: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "idle" + ]</b>, + ... +}</pre>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/management.html b/chrome/common/extensions/docs/templates/intros/management.html new file mode 100644 index 0000000..ae5076a --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/management.html @@ -0,0 +1,23 @@ +<p id="classSummary"> +The <code>chrome.management</code> module provides ways to manage the list of extensions/apps that are installed and running. It is particularly useful for extensions that <a href="override.html">override</a> the built-in New Tab page. +</p> + +<h2 id="manifest">Manifest</h2> + +<p>You must declare the "management" permission +in the <a href="manifest.html">extension manifest</a> +to use the management API. +For example:</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "management" + ]</b>, + ... +}</pre> + +<p> +The one method that doesn't require the "management" permission is +<a href="#method-getPermissionWarningsByManifest"><code>getPermissionWarningsByManifest</code></a> +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/mediaGalleries.html b/chrome/common/extensions/docs/templates/intros/mediaGalleries.html new file mode 100644 index 0000000..82dbb9a --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/mediaGalleries.html @@ -0,0 +1,50 @@ +<p> +The media galleries API allows you to access media files (images, +video, audio) from the user's local disks (with the user's consent). +</p> + +<p> +Using the API, you can prompt the user for permission to access the media +galleries. The permission dialog will contain common media locations for +the platform and will allow the user to add additional locations. From those +locations, only media files will be present in the file system objects. +</p> + +<h2 id="manifest">Manifest</h2> +<p>The media galleries API has two axes of permission parameters; the locations +that can be accessed, and the type of access (read-only, read-write, +add-files).</p> + +<p>On the location axis, specifying no location-type permission parameters +means that +no media galleries are accessible until the user grants permission to +specific media galleries at runtime using the media gallery configuration +dialog. This dialog can be programmatically triggered. Alternatively, +specifying the "all-auto-detected" permission parameter grants access to all +auto-detected media galleries on the user's computer. However, this +permission displays an install time prompt indicating that the extension +will have access to all of the user's media files.</p> + +<p>On the access type axis, the "read" permission parameter grants the +extension the right to read files. This permission does not trigger an install +time permission prompt because the user must still grant access to particular +galleries, either with the "all-auto-detected" permission parameter or at +runtime by using the media gallery management dialog. For example:</p> + +<pre>{ + "name": "My extension", + ... + "permissions": [ + <b>{ "mediaGalleries": ["read", "all-auto-detected"] }</b> + ], + ... +}</pre> + +<p>This permission will trigger an install time permission prompt +and let the extension read from all auto-detected media galleries on the +user's computer. The user may add or remove galleries using the +media gallery management dialog, after which the extension will be able +to read all the media files from galleries that the user has selected.</p> + +<p>Currently "read" is the only access type supported by +this API. Read-write and add-file access with be implemented soon.</p> diff --git a/chrome/common/extensions/docs/templates/intros/omnibox.html b/chrome/common/extensions/docs/templates/intros/omnibox.html new file mode 100644 index 0000000..9c34655 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/omnibox.html @@ -0,0 +1,75 @@ +<p> +The omnibox API allows you to register a +keyword with Google Chrome's address bar, +which is also known as the omnibox. +</p> + +<p> +<img src="{{static}}/images/omnibox.png" width="300" height="150" + alt="A screenshot showing suggestions related to the keyword 'Chromium Search'"/> +</p> + +<p> +When the user enters your extension's +keyword, the user starts +interacting solely with your extension. +Each keystroke is sent to your +extension, and you can provide suggestions +in response. +</p> + +<p> +The suggestions can be richly formatted +in a variety of ways. + +When the user accepts +a suggestion, your extension is notified +and can take action. +</p> + +<h2 id="manifest">Manifest</h2> + +<p> +You must include an <code>omnibox</code> <code>keyword</code> field +in the <a href="manifest.html">manifest</a> +to use the omnibox API. +You should also +specify a 16x16-pixel icon, which will be +displayed in the address bar when suggesting that users +enter keyword mode. +</p> + +<p> +For example: +</p> + +<pre>{ + "name": "Aaron's omnibox extension", + "version": "1.0", + <b>"omnibox": { "keyword" : "aaron" },</b> + <b>"icons": {</b> + <b>"16": "16-full-color.png"</b> + <b>},</b> + "background": { + "persistent": false, + "scripts": ["background.js"] + } +}</pre> + +<p class="note"> +<strong>Note:</strong> +Chrome automatically creates a grayscale version of +your 16x16-pixel icon. You should provide +a full-color version so that it can also be +used in other situations that require color. +For example, the <a href="contextMenus.html" +>context menus API</a> also uses a 16x16-pixel +icon, but it is displayed in color. +</p> + + +<h2 id="examples">Examples</h2> + +<p> +You can find samples of this API on the +<a href="samples.html#omnibox">sample page</a>. diff --git a/chrome/common/extensions/docs/templates/intros/pageAction.html b/chrome/common/extensions/docs/templates/intros/pageAction.html new file mode 100644 index 0000000..86930f1 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/pageAction.html @@ -0,0 +1,108 @@ +<p> +Use page actions to put icons inside the address bar. +Page actions represent actions +that can be taken on the current page, +but that aren't applicable to all pages. +Some examples: +</p> +<ul> + <li> Subscribe to this page's RSS feed </li> + <li> Make a slideshow out of this page's photos </li> +</ul> + +<p> +The RSS icon in the following screenshot +represents a page action +that lets you subscribe to +the RSS feed for the current page. +</p> + +<img src="{{static}}/images/page-action.png" + width="361" height="79" /> + +<p> +If you want the extension's icon to always be visible, +use a <a href="browserAction.html">browser action</a> instead. +</p> + +<p class="caution"> +<strong>Note:</strong> +Packaged apps cannot use page actions. +</p> + + +<h2 id="manifest">Manifest</h2> + +<p> +Register your page action in the +<a href="manifest.html">extension manifest</a> +like this: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"page_action": { + "default_icon": "icons/foo.png", <em>// optional</em> + "default_title": "Do action", <em>// optional; shown in tooltip</em> + "default_popup": "popup.html" <em>// optional</em> + }</b>, + ... +}</pre> + +<h2 id="ui">Parts of the UI</h2> + +<p> +Like browser actions, +page actions can have an icon, +a tooltip, and popup; +they can't have badges, however. +In addition, page actions can appear and disappear. +You can find information about icons, tooltips, and popups +by reading about the +<a href="browserAction.html#ui">browser action UI</a>. +</p> + +<p> +You make a page action appear and disappear using the +<a href="#method-show">show()</a> and +<a href="#method-hide">hide()</a> methods, respectively. +By default, a page action is hidden. +When you show it, you specify the tab +in which the icon should appear. +The icon remains visible +until the tab is closed +or starts displaying a different URL +(because the user clicks a link, for example). +</p> + + + + +<h2 id="tips">Tips</h2> + +<p>For the best visual impact, +follow these guidelines:</p> + +<ul> + <li><b>Do</b> use page actions + for features that make sense + for only a few pages. + <li><b>Don't</b> use page actions + for features that make sense + for most pages. + Use <a href="browserAction.html">browser actions</a> instead. + <li><b>Don't</b> constantly animate your icon. + That's just annoying. +</ul> + + +<h2 id="examples"> Examples </h2> + +<p> +You can find simple examples of using page actions in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/pageAction/">examples/api/pageAction</a> +directory. +For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/pageCapture.html b/chrome/common/extensions/docs/templates/intros/pageCapture.html new file mode 100644 index 0000000..abb0af3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/pageCapture.html @@ -0,0 +1,30 @@ +<p> +The pageCapture API allows you to save a tab as MHTML. +</p> + +<p> +MHTML is a <a href="http://tools.ietf.org/html/rfc2557">standard format</a> +supported by most browsers. It encapsulates in a single file a page and all +its resources (CSS files, images..). +</p> + +<p> +Note that for security reasons a MHTML file can only be loaded from the file +system and that it can only be loaded in the main frame. +</p> + +<h2 id="manifest">Manifest</h2> + + +<p>You must declare the "pageCapture" permission +in the <a href="manifest.html">extension manifest</a> +to use the history API. +For example:</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "pageCapture" + ]</b>, + ... +}</pre>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/permissions.html b/chrome/common/extensions/docs/templates/intros/permissions.html new file mode 100644 index 0000000..a4f49d3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/permissions.html @@ -0,0 +1,173 @@ +<p id="classSummary"> + Use the <code>chrome.permissions</code> module to implement + optional permissions. You can request optional permissions during your + extension's regular application flow rather than at install time, so users + understand why the permissions are needed and use only those that are + necessary. +</p> + +<p> + For general information about permissions and details about each permission, + see the <a href="manifest.html#permissions">permissions</a> section of the + manifest documentation. +</p> + +<h2 id="howto"> Implementing optional permissions </h2> + +<h3 id="types"> + Step 1: Decide which permissions are optional and required +</h3> +<p> + Extensions should generally require permissions when they are needed for the + extension's basic functionality and employ optional permissions for optional + features. +</p> + +<p> + Advantages of optional permissions: + <ul> + <li> + Users run with less permissions since they enable only what is needed. + </li> + <li> + The extension can help explain why it needs particular permissions by + requesting them when the user enables the relevant feature. + </li> + <li> + Chrome can avoid disabling extensions that upgrade if they add permissions + as optional rather than required. + </li> + </ul> +</p> + +<p> + Advantages of required permissions: + <ul> + <li> + The extension can prompt the user once to accept all permissions. + </li> + <li> + They simplify extension development by guaranteeing which permissions are + present. + </li> + </ul> +</p> + + +<h3 id="manifest"> Step 2: Declare optional permissions in the manifest </h3> +<p> + Declare optional permissions in your <a href="manifest.html">extension + manifest</a> with the <code>optional_permissions</code> key, using the + same format as the <a href="manifest.html#permissions">permissions</a> + field: + +<pre>{ + "name": "My extension", + ... + <b>"optional_permissions": [ "tabs", "http://www.google.com/" ],</b> + ... +}</pre> +</p> + +<p> +You can specify any of the following as optional permissions: +<ul> + <li><i>host permissions</i></li> + <li>appNotifications</li> + <li>background</li> + <li>bookmarks</li> + <li>clipboardRead</li> + <li>clipboardWrite</li> + <li>contentSettings</li> + <li>contextMenus</li> + <li>cookies</li> + <li>debugger</li> + <li>history</li> + <li>idle</li> + <li>management</li> + <li>notifications</li> + <li>pageCapture</li> + <li>tabs</li> + <li>topSites</li> + <li>webNavigation</li> + <li>webRequest</li> + <li>webRequestBlocking</li> +</ul> +</p> + +<h3 id="request"> Step 3: Request optional permissions </h3> +<p> + Request the permissions from within a user gesture using + <code>permissions.request()</code>: +<pre> +document.querySelector('#my-button').addEventListener('click', function(event) { + // Permissions must be requested from inside a user gesture, like a button's + // click handler. + chrome.permissions.request({ + permissions: ['tabs'], + origins: ['http://www.google.com/'] + }, function(granted) { + // The callback argument will be true if the user granted the permissions. + if (granted) { + doSomething(); + } else { + doSomethingElse(); + } + }); +}); +</pre> +</p> + +<p> + Chrome prompts the user if adding the permissions results in different + <a href="permission_warnings.html">warning messages</a> than the user has + already seen and accepted. For example, the previous code might result in + a prompt like this: +</p> + +<p style="text-align: center"> + <img src="{{static}}/images/perms-optional.png" + alt="example permission confirmation prompt" + width="416" height="234"> +</p> + +<h3 id="contains"> Step 4: Check the extension's current permissions </h3> +<p> + To check whether your extension has a specific permission or set of + permissions, use <code>permission.contains()</code>: +</p> + +<pre> +chrome.permissions.contains({ + permissions: ['tabs'], + origins: ['http://www.google.com/'] +}, function(result) { + if (result) { + // The extension has the permissions. + } else { + // The extension doesn't have the permissions. + } +}); +</pre> + +<h3 id="remove"> Step 5: Remove the permissions </h3> +<p> + You should remove permissions when you no longer need them. + After a permission has been removed, calling + <code>permissions.request()</code> usually adds the permission back without + prompting the user. +</p> + +<pre> +chrome.permissions.remove({ + permissions: ['tabs'], + origins: ['http://www.google.com/'] +}, function(removed) { + if (removed) { + // The permissions have been removed. + } else { + // The permissions have not been removed (e.g., you tried to remove + // required permissions). + } +}); +</pre>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/privacy.html b/chrome/common/extensions/docs/templates/intros/privacy.html new file mode 100644 index 0000000..c7657ea --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/privacy.html @@ -0,0 +1,209 @@ +<p id="classSummary"> + Use the <code>chrome.privacy</code> module to control usage of the features in + Chrome that can affect a user's privacy. This module relies on the + <a href="types.html#ChromeSetting">ChromeSetting prototype of the type API</a> + for getting and setting Chrome's configuration. +</p> + +<p class="note"> + The <a href="http://www.google.com/intl/en/landing/chrome/google-chrome-privacy-whitepaper.pdf">Chrome Privacy Whitepaper</a> + gives background detail regarding the features which this API can control. +</p> + +<h2 id="manifest">Manifest</h2> +<p> + You must declare the "privacy" permission in your extension's + <a href="manifest.html">manifest</a> to use the API. For example: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "privacy" + ]</b>, + ... +}</pre> + +<h2 id="usage">Usage</h2> + +<p> + Reading the current value of a Chrome setting is straightforward. You'll first + need to find the property you're interested in, then you'll call + <code>get()</code> on that object in order to retrieve its current value and + your extension's level of control. For example, to determine if Chrome's + Autofill feature is enabled, you'd write: +</p> + +<pre>chrome.privacy.services.autofillEnabled.get({}, function(details) { + if (details.value) + console.log('Autofill is on!'); + else + console.log('Autofill is off!'); +});</pre> + +<p> + Changing the value of a setting is a little bit more complex, simply because + you first must verify that your extension can control the setting. The user + won't see any change to her settings if your extension toggles a setting that + is either locked to a specific value by enterprise policies + (<code>levelOfControl</code> will be set to "not_controllable"), or if another + extension is controlling the value (<code>levelOfControl</code> will be set to + "controlled_by_other_extensions"). The <code>set()</code> call will succeed, + but the setting will be immediately overridden. As this might be confusing, it + is advisable to warn the user when the settings they've chosen aren't + practically applied. +</p> + +<p class="note"> + Full details about extensions' ability to control <code>ChromeSetting</code>s + can be found under + <a href="types.html#ChromeSetting"> + <code>chrome.types.ChromeSetting</code></a>. +</p> + +<p> + This means that you ought to use the <code>get()</code> method to determine + your level of access, and then only call <code>set()</code> if your extension + can grab control over the setting (in fact if your extension can't control the + setting it's probably a good idea to visually disable the functionality to + reduce user confusion): +</p> + +<pre>chrome.privacy.services.autofillEnabled.get({}, function(details) { + if (details.levelOfControl === 'controllable_by_this_extension') { + chrome.privacy.services.autofillEnabled.set({ value: true }, function() { + if (chrome.extension.lastError === undefined) + console.log("Hooray, it worked!"); + else + console.log("Sadness!", chrome.extension.lastError); + } + } +});</pre> + +<p> + If you're interested in changes to a setting's value, add a listener to its + <code>onChange</code> event. Among other uses, this will allow you to warn the + user if a more recently installed extension grabs control of a setting, or if + enterprise policy overrides your control. To listen for changes to Autofill's + status, for example, the following code would suffice: +</p> + +<pre>chrome.privacy.services.autofillEnabled.onChange.addListener( + function (details) { + // The new value is stored in `details.value`, the new level of control + // in `details.levelOfControl`, and `details.incognitoSpecific` will be + // `true` if the value is specific to Incognito mode. + });</pre> + +<h2 id="examples">Examples</h2> +<p> + For example code, see the + <a href="samples.html#privacy">Privacy API samples</a>. +</p> + + + +<p id="classSummary"> + Use the <code>chrome.privacy</code> module to control usage of the features in + Chrome that can affect a user's privacy. This module relies on the + <a href="types.html#ChromeSetting">ChromeSetting prototype of the type API</a> + for getting and setting Chrome's configuration. +</p> + +<p class="note"> + The <a href="http://www.google.com/intl/en/landing/chrome/google-chrome-privacy-whitepaper.pdf">Chrome Privacy Whitepaper</a> + gives background detail regarding the features which this API can control. +</p> + +<h2 id="manifest">Manifest</h2> +<p> + You must declare the "privacy" permission in your extension's + <a href="manifest.html">manifest</a> to use the API. For example: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "privacy" + ]</b>, + ... +}</pre> + +<h2 id="usage">Usage</h2> + +<p> + Reading the current value of a Chrome setting is straightforward. You'll first + need to find the property you're interested in, then you'll call + <code>get()</code> on that object in order to retrieve its current value and + your extension's level of control. For example, to determine if Chrome's + Autofill feature is enabled, you'd write: +</p> + +<pre>chrome.privacy.services.autofillEnabled.get({}, function(details) { + if (details.value) + console.log('Autofill is on!'); + else + console.log('Autofill is off!'); +});</pre> + +<p> + Changing the value of a setting is a little bit more complex, simply because + you first must verify that your extension can control the setting. The user + won't see any change to her settings if you extension toggles a setting that + is either locked to a specific value by enterprise policies + (<code>levelOfControl</code> will be set to "not_controllable"), or if another + extension is controlling the value (<code>levelOfControl</code> will be set to + "controlled_by_other_extensions"). The <code>set()</code> call will succeed, + but the setting will be immediately overridden. As this might be confusing, it + is advisable to warn the user when the settings they've chosen aren't + practically applied. +</p> + +<p class="note"> + Full details about extensions' ability to control <code>ChromeSetting</code>s + can be found under + <a href="types.html#ChromeSetting"> + <code>chrome.types.ChromeSetting</code></a>. +</p> + +<p> + This means that you ought to use the <code>get()</code> method to determine + your level of access, and then only call <code>set()</code> if your extension + can grab control over the setting (in fact if your extension can't control the + setting it's probably a good idea to visibly disable the functionality to + reduce user confusion): +</p> + +<pre>chrome.privacy.services.autofillEnabled.get({}, function(details) { + if (details.levelOfControl === 'controllable_by_this_extension') { + chrome.privacy.services.autofillEnabled.set({ value: true }, function() { + if (chrome.extension.lastError === undefined) + console.log("Hooray, it worked!"); + else + console.log("Sadness!", chrome.extension.lastError); + } + } +});</pre> + +<p> + If you're interested in changes to a setting's value, add a listener to its + <code>onChange</code> event. Among other uses, this will allow you to warn the + user if a more recently installed extension grabs control of a setting, or if + enterprise policy overrides your control. To listen for changes to Autofill's + status, for example, the following code would suffice: +</p> + +<pre>chrome.privacy.services.autofillEnabled.onChange.addListener( + function (details) { + // The new value is stored in `details.value`, the new level of control + // in `details.levelOfControl`, and `details.incognitoSpecific` will be + // `true` if the value is specific to Incognito mode. + });</pre> + +<h2 id="examples">Examples</h2> +<p> + For example code, see the + <a href="samples.html#privacy">Privacy API samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/proxy.html b/chrome/common/extensions/docs/templates/intros/proxy.html new file mode 100644 index 0000000..9cfea92 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/proxy.html @@ -0,0 +1,214 @@ +<p id="classSummary"> +Use the <code>chrome.proxy</code> module to manage Chrome's +proxy settings. This module relies on the <a href="types.html#ChromeSetting"> +ChromeSetting prototype of the type API</a> for getting and setting the proxy +configuration. +</p> + +<h2 id="manifest">Manifest</h2> +<p>You must declare the "proxy" permission +in the <a href="manifest.html">extension manifest</a> +to use the proxy settings API. +For example:</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "proxy" + ]</b>, + ... +}</pre> + +<h2 id="description">Objects and properties</h2> + +<p> +Proxy settings are defined in a +<a href="#type-ProxyConfig"><code>ProxyConfig</code></a> object. Depending on +Chrome's proxy settings, the settings may contain +<a href="#type-ProxyRules"><code>ProxyRules</code></a> or a <a + href="#type-PacScript"><code>PacScript</code></a>. +</p> + +<h3 id="proxy_modes">Proxy modes</h3> + +<p> +A ProxyConfig object's <code>mode</code> attribute determines the overall +behavior of Chrome with regards to proxy usage. It can take the following +values: +<dl> + <dt><code>direct</code></dt> + <dd>In <code>direct</code> mode all connections are created directly, without + any proxy involved. This mode allows no further parameters in the + <code>ProxyConfig</code> object.</dd> + + <dt><code>auto_detect</code></dt> + <dd>In <code>auto_detect</code> mode the proxy configuration is determined by + a PAC script that can be downloaded at + <a href="http://wpad/wpad.dat">http://wpad/wpad.dat</a>. + This mode allows no further parameters in the <code>ProxyConfig</code> + object.</dd> + + <dt><code>pac_script</code></dt> + <dd>In <code>pac_script</code> mode the proxy configuration is determined by + a PAC script that is either retrieved from the URL specified in the + <a href="#type-PacScript"><code>PacScript</code></a> object or + taken literally from the <code>data</code> element specified in the + <a href="#type-PacScript"><code>PacScript</code></a> object. + Besides this, this mode allows no further parameters in the + <code>ProxyConfig</code> object.</dd> + + <dt><code>fixed_servers</code></dt> + <dd>In <code>fixed_servers</code> mode the proxy configuration is codified in + a <a href="#type-ProxyRules><code>ProxyRules"><code>ProxyRules</code></a> + object. Its structure is described in <a href="#proxy_rules">Proxy rules</a>. + Besides this, the <code>fixed_servers</code> mode allows no further parameters + in the <code>ProxyConfig</code> object.</dd> + + <dt><code>system</code></dt> + <dd>In <code>system</code> mode the proxy configuration is taken from the + operating system. This mode allows no further parameters in the + <code>ProxyConfig</code> object. Note that the <code>system</code> mode is + different from setting no proxy configuration. In the latter case, Chrome + falls back to the system settings only if no command-line options influence + the proxy configuration.</dd> +</dl> +</p> + +<h3 id="proxy_rules">Proxy rules</h3> + +<p> +The <a href="#type-ProxyRules"><code>ProxyRules</code></a> object can contain +either a <code>singleProxy</code> attribute or a subset of +<code>proxyForHttp</code>, <code>proxyForHttps</code>, <code>proxyForFtp</code>, +and <code>fallbackProxy</code>. +</p> + +<p> +In the first case, HTTP, HTTPS and FTP traffic is proxied through the specified +proxy server. Other traffic is sent directly. In the latter case the behavior is +slightly more subtle: If a proxy server is configured for the HTTP, HTTPS or FTP +protocol, the respective traffic is proxied through the specified server. If no +such proxy server is specified or traffic uses a different protocol than HTTP, +HTTPS or FTP, the <code>fallbackProxy</code> is used. If no +<code>fallbackProxy</code> is specified, traffic is sent directly without a +proxy server. +</p> + +<h3 id="proxy_server_objects">Proxy server objects</h3> + +<p> +A proxy server is configured in a +<a href="#type-ProxyServer"><code>ProxyServer</code></a> object. The connection +to the proxy server (defined by the <code>host</code> attribute) uses the +protocol defined in the <code>scheme</code> attribute. If no <code>scheme</code> +is specified, the proxy connection defaults to <code>http</code>. +</p> + +<p> +If no <code>port</code> is defined in a +<a href="#type-ProxyServer"><code>ProxyServer</code></a> object, the port is +derived from the scheme. The default ports are: +<table> + <tr><th>Scheme</th><th>Port</th></tr> + <tr><td>http</td><td>80</td></tr> + <tr><td>https</td><td>443</td></tr> + <tr><td>socks4</td><td>1080</td></tr> + <tr><td>socks5</td><td>1080</td></tr> +</table> +</p> + +<h3 id="bypass_list">Bypass list</h3> + +<p> +Individual servers may be excluded from being proxied with the +<code>bypassList</code>. This list may contain the following entries: +<dl> + <dt><code>[<em><scheme></em>://]<em><host-pattern></em>[:<em><port></em>]</code></dt> + <dd>Match all hostnames that match the pattern <em><host-pattern></em>.<br> + Examples: <code>"foobar.com", "*foobar.com", "*.foobar.com", "*foobar.com:99", + "https://x.*.y.com:99"</code></dd> + + <dt><code>[<em><scheme></em>://]<em><ip-literal></em>[:<em><port></em>]</code></dt> + <dd>Match URLs that are IP address literals.<br> + Conceptually this is the similar to the first case, but with special cases + to handle IP literal canonicalization. For example, matching + on "[0:0:0::1]" is the same as matching on "[::1]" because + the IPv6 canonicalization is done internally.<br> + Examples: <code>"127.0.1", "[0:0::1]", "[::1]", "http://[::1]:99"</code></dd> + + <dt><code><em><ip-literal></em>/<em><prefix-length-in-bits></em></code></dt> + <dd>Match any URL containing an IP literal within the given range. The IP + range is specified using CIDR notation.<br> + Examples: <code>"192.168.1.1/16", "fefe:13::abc/33"</code></dd> + + <dt><code><local></code></dt> + <dd>Match local addresses. An address is local if the host is "127.0.0.1", + "::1", or "localhost".<br> + Example: <code>"<local>"</code></dd> +</dl> + + +<h2 id="overview-examples">Examples</h2> + +<p> +The following code sets a SOCKS 5 proxy for HTTP connections to all servers but +foobar.com and uses direct connections for all other protocols. The settings +apply to regular and incognito windows, as incognito windows inherit settings +from regular windows. Please also consult the <a + href="types.html#ChromeSetting">Types API</a> documentation. +</p> + +<pre> +var config = { + mode: "fixed_servers", + rules: { + proxyForHttp: { + scheme: "socks5", + host: "1.2.3.4" + }, + bypassList: ["foobar.com"] + } +}; +chrome.proxy.settings.set( + {value: config, scope: 'regular'}, + function() {}); +</pre> + +<p> +The following code sets a custom PAC script. +</p> + +<pre> +var config = { + mode: "pac_script", + pacScript: { + data: "function FindProxyForURL(url, host) {\n" + + " if (host == 'foobar.com')\n" + + " return 'PROXY blackhole:80';\n" + + " return 'DIRECT';\n" + + "}" + } +}; +chrome.proxy.settings.set( + {value: config, scope: 'regular'}, + function() {}); +</pre> + +<p> +The next snippet queries the currently effective proxy settings. The effective +proxy settings can be determined by another extension or by a policy. See the <a + href="types.html#ChromeSetting">Types API</a> documentation for details. +</p> + +<pre> +chrome.proxy.settings.get( + {'incognito': false}, + function(config) {console.log(JSON.stringify(config));}); +</pre> + +<p> +Note that the <code>value</code> object passed to <code>set()</code> is not +identical to the <code>value</code> object passed to callback function of +<code>get()</code>. The latter will contain a +<code>rules.proxyForHttp.port</code> element. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/socket.html b/chrome/common/extensions/docs/templates/intros/socket.html new file mode 100644 index 0000000..10b59a4 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/socket.html @@ -0,0 +1,10 @@ +<p id="classSummary"> +Use the <code>chrome.socket</code> module +to send and receive data over the network +using TCP and UDP connections. +</p> + +<p> +Read the <a href="app_network.html">Network Communications</a> documentation +to find out how to use this API. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/storage.html b/chrome/common/extensions/docs/templates/intros/storage.html new file mode 100644 index 0000000..50dcd2e --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/storage.html @@ -0,0 +1,139 @@ +<p id="classSummary"> +Use the <code>chrome.storage</code> module +to store, retrieve, and track changes to user data. +This API has been optimized +to meet the specific storage needs of extensions. +It provides the same storage capabilities as the +<a href="https://developer.mozilla.org/en/DOM/Storage#localStorage">localStorage API</a> +with the following key differences: +</p> + +<ul> + <li>User data can be automatically synced with Chrome sync + (using <code>storage.sync</code>).</li> + <li>Your extension's content scripts can directly access user data + without the need for a background page.</li> + <li>A user's extension settings can be persisted + even when using + <a href="manifest.html#incognito">split incognito behavior</a>.</li> + <li>User data can be stored as objects + (the <code>localStorage API</code> stores data in strings).</li> +</ul> + +<h2 id="manifest">Manifest</h2> +<p>You must declare the "storage" permission in the <a + href="manifest.html">extension manifest</a> + to use the storage API. + For example:</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "storage" + ]</b>, + ... +}</pre> + +<h2 id="using-sync">Usage</h2> + +<p> +To store user data for your extension, +you can use either +<code>storage.sync</code> or +<code>storage.local</code>. +When using <code>storage.sync</code>, +the stored data will automatically be synced +to any Chrome browser that the user is logged into, +provided the user has sync enabled. +</p> + +<p> +When Chrome is offline, +Chrome stores the data locally. +The next time the browser is online, +Chrome syncs the data. +Even if a user disables syncing, +<code>storage.sync</code> will still work. +In this case, it will behave identically +to <code>storage.local</code>. +</p> + +<p class="warning"> +Confidential user information should not be stored! +The storage area isn't encrypted. +</p> + +<h2 id="limits">Storage and throttling limits</h2> + +<p><code>chrome.storage</code> is not a big truck. +It's a series of tubes. +And if you don't understand, +those tubes can be filled, +and if they are filled +when you put your message in, +it gets in line, +and it's going to be delayed +by anyone that puts into that tube +enormous amounts of material. + +<p>For details on the current limits +of the storage API, and what happens +when those limits are exceeded, please +see the <a href="#apiReference">API reference</a>. + + +<h2 id="examples">Examples</h2> + +<p> +The following example checks for +CSS code saved by a user on a form, +and if found, +stores it. +</p> + +<pre> +function saveChanges() { + // Get a value saved in a form. + var theValue = textarea.value; + // Check that there's some code there. + if (!theValue) { + message('Error: No value specified'); + return; + } + // Save it using the Chrome extension storage API. + chrome.storage.sync.set({'value': theValue}, function() { + // Notify that we saved. + message('Settings saved'); + }); +} +</pre> + +<p> +If you're interested in tracking changes made +to a data object, +you can add a listener +to its <code>onChanged</code> event. +Whenever anything changes in storage, +that event fires. +Here's sample code +to listen for saved changes: +</p> + +<pre> +chrome.storage.onChanged.addListener(function(changes, namespace) { + for (key in changes) { + var storageChange = changes[key]; + console.log('Storage key "%s" in namespace "%s" changed. ' + + 'Old value was "%s", new value is "%s".', + key, + namespace, + storageChange.oldValue, + storageChange.newValue); + } +}); +</pre> + +<p> +You can find examples that use this API on the +<a href="samples.html#sty">Samples page</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/tabs.html b/chrome/common/extensions/docs/templates/intros/tabs.html new file mode 100644 index 0000000..8002b16 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/tabs.html @@ -0,0 +1,45 @@ +<p id="classSummary"> +Use the <code>chrome.tabs</code> module +to interact with the browser's tab system. +You can use this module to +create, modify, and rearrange tabs in the browser. +</p> + +<img src="{{static}}/images/tabs.png" + width="323" height="50" alt="Two tabs in a window" /> + +<h2 id="manifest">Manifest</h2> +<p> +Almost all <code>chrome.tabs</code> methods require you to +declare the "tabs" permission +in the <a href="manifest.html">extension manifest</a>. +For example: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "tabs" + ]</b>, + ... +}</pre> + +<p> +Three methods (<a href="#method-create"><code>create</code></a>, +<a href="#method-update"><code>update</code></a> and +<a href="#method-remove"><code>remove</code></a>) and one event +(<a href="#event-onRemoved"><code>onRemoved</code></a>) don't require the "tabs" +permission. +</p> + + +<h2 id="examples"> Examples </h2> + +<p> +You can find simple examples of using the tabs module in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/">examples/api/tabs</a> +directory. +For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/topSites.html b/chrome/common/extensions/docs/templates/intros/topSites.html new file mode 100644 index 0000000..f5eb1e5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/topSites.html @@ -0,0 +1,30 @@ +<h2 id="manifest">Notes</h2> + +<p> +The top sites module allows access to the top sites that are displayed on +the new tab page. +</p> + +<h2 id="manifest">Manifest</h2> + +<p> +You must declare the "topSites" permission in your extension's manifest +to use this API. +</p> + +<pre>{ + "name": "My extension", + ... +<b> "permissions": [ + "topSites", + ]</b>, + ... +}</pre> + + +<h2 id="examples">Examples</h2> + +<p> +You can find samples of this API in +<a href="samples.html#topsites">Samples</a>. +</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/tts.html b/chrome/common/extensions/docs/templates/intros/tts.html new file mode 100644 index 0000000..7e27b61 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/tts.html @@ -0,0 +1,186 @@ +<p id="classSummary"> +Use the <code>chrome.tts</code> module to play synthesized +text-to-speech (TTS) from your extension or packaged app. +See also the related +<a href="ttsEngine.html">ttsEngine</a> +module, which allows an extension to implement a speech engine. +</p> + + +<h2 id="overview">Overview</h2> + +<p>You must declare the "tts" permission +in your extension's manifest to use this API. +</p> + +<p>Chrome provides native support for speech on Windows (using SAPI +5), Mac OS X, and Chrome OS, using speech synthesis capabilities +provided by the operating system. On all platforms, the user can +install extensions that register themselves as alternative speech +engines.</p> + +<h2 id="generating_speech">Generating speech</h2> + +<p>Call <code>speak()</code> from your extension or +packaged app to speak. For example:</p> + +<pre>chrome.tts.speak('Hello, world.');</pre> + +<p>To stop speaking immediately, just call <code>stop()</code>: + +<pre>chrome.tts.stop();</pre> + +<p>You can provide options that control various properties of the speech, +such as its rate, pitch, and more. For example:</p> + +<pre>chrome.tts.speak('Hello, world.', {'rate': 2.0});</pre> + +<p>It's also a good idea to specify the language so that a synthesizer +supporting that language (and regional dialect, if applicable) is chosen.</p> + +<pre>chrome.tts.speak( + 'Hello, world.', {'lang': 'en-US', 'rate': 2.0});</pre> + +<p>By default, each call to <code>speak()</code> interrupts any +ongoing speech and speaks immediately. To determine if a call would be +interrupting anything, you can call <code>isSpeaking()</code>. In +addition, you can use the <code>enqueue</code> option to cause this +utterance to be added to a queue of utterances that will be spoken +when the current utterance has finished.</p> + +<pre>chrome.tts.speak( + 'Speak this first.'); +chrome.tts.speak( + 'Speak this next, when the first sentence is done.', {'enqueue': true}); +</pre> + +<p>A complete description of all options can be found in the +<a href="#method-speak">speak() method documentation</a> below. +Not all speech engines will support all options.</p> + +<p>To catch errors and make sure you're calling <code>speak()</code> +correctly, pass a callback function that takes no arguments. Inside +the callback, check +<a href="extension.html#property-lastError">chrome.extension.lastError</a> +to see if there were any errors.</p> + +<pre>chrome.tts.speak( + utterance, + options, + function() { + if (chrome.extension.lastError) { + console.log('Error: ' + chrome.extension.lastError.message); + } + });</pre> + +<p>The callback returns right away, before the engine has started +generating speech. The purpose of the callback is to alert you to +syntax errors in your use of the TTS API, not to catch all possible +errors that might occur in the process of synthesizing and outputting +speech. To catch these errors too, you need to use an event listener, +described below.</p> + +<h2 id="events">Listening to events</h2> + +<p>To get more real-time information about the status of synthesized speech, +pass an event listener in the options to <code>speak()</code>, like this:</p> + +<pre>chrome.tts.speak( + utterance, + { + onEvent: function(event) { + console.log('Event ' + event.type ' at position ' + event.charIndex); + if (event.type == 'error') { + console.log('Error: ' + event.errorMessage); + } + } + }, + callback);</pre> + +<p>Each event includes an event type, the character index of the current +speech relative to the utterance, and for error events, an optional +error message. The event types are:</p> + +<ul> + <li><code>'start'</code>: The engine has started speaking the utterance. + <li><code>'word'</code>: A word boundary was reached. Use + <code>event.charIndex</code> to determine the current speech + position. + <li><code>'sentence'</code>: A sentence boundary was reached. Use + <code>event.charIndex</code> to determine the current speech + position. + <li><code>'marker'</code>: An SSML marker was reached. Use + <code>event.charIndex</code> to determine the current speech + position. + <li><code>'end'</code>: The engine has finished speaking the utterance. + <li><code>'interrupted'</code>: This utterance was interrupted by another + call to <code>speak()</code> or <code>stop()</code> and did not + finish. + <li><code>'cancelled'</code>: This utterance was queued, but then + cancelled by another call to <code>speak()</code> or + <code>stop()</code> and never began to speak at all. + <li><code>'error'</code>: An engine-specific error occurred and + this utterance cannot be spoken. + Check <code>event.errorMessage</code> for details. +</ul> + +<p>Four of the event types—<code>'end'</code>, <code>'interrupted'</code>, +<code>'cancelled'</code>, and <code>'error'</code>—are <i>final</i>. +After one of those events is received, this utterance will no longer +speak and no new events from this utterance will be received.</p> + +<p>Some voices may not support all event types, and some voices may not +send any events at all. If you do not want to use a voice unless it sends +certain events, pass the events you require in the +<code>requiredEventTypes</code> member of the options object, or use +<code>getVoices()</code> to choose a voice that meets your requirements. +Both are documented below.</p> + +<h2 id="ssml">SSML markup</h2> + +<p>Utterances used in this API may include markup using the +<a href="http://www.w3.org/TR/speech-synthesis">Speech Synthesis Markup +Language (SSML)</a>. If you use SSML, the first argument to +<code>speak()</code> should be a complete SSML document with an XML +header and a top-level <code><speak></code> tag, not a document +fragment.</p> + +<p>For example:</p> + +<pre>chrome.tts.speak( + '<?xml version="1.0"?>' + + '<speak>' + + ' The <emphasis>second</emphasis> ' + + ' word of this sentence was emphasized.' + + '</speak>');</pre> + +<p>Not all speech engines will support all SSML tags, and some may not support +SSML at all, but all engines are required to ignore any SSML they don't +support and to still speak the underlying text.</p> + +<h2 id="choosing_voice">Choosing a voice</h2> + +<p>By default, Chrome chooses the most appropriate voice for each +utterance you want to speak, based on the language and gender. On most +Windows, Mac OS X, and Chrome OS systems, speech synthesis provided by +the operating system should be able to speak any text in at least one +language. Some users may have a variety of voices available, though, +from their operating system and from speech engines implemented by other +Chrome extensions. In those cases, you can implement custom code to choose +the appropriate voice, or to present the user with a list of choices.</p> + +<p>To get a list of all voices, call <code>getVoices()</code> and pass it +a function that receives an array of <code>TtsVoice</code> objects as its +argument:</p> + +<pre>chrome.tts.getVoices( + function(voices) { + for (var i = 0; i < voices.length; i++) { + console.log('Voice ' + i + ':'); + console.log(' name: ' + voices[i].voiceName); + console.log(' lang: ' + voices[i].lang); + console.log(' gender: ' + voices[i].gender); + console.log(' extension id: ' + voices[i].extensionId); + console.log(' event types: ' + voices[i].eventTypes); + } + });</pre>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/ttsEngine.html b/chrome/common/extensions/docs/templates/intros/ttsEngine.html new file mode 100644 index 0000000..38febe7 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/ttsEngine.html @@ -0,0 +1,155 @@ +<p id="classSummary"> +Use the <code>chrome.ttsEngine</code> module to +implement a text-to-speech (TTS) engine using an extension. If your +extension registers using this API, it will receive events containing +an utterance to be spoken and other parameters when any extension or packaged +app uses the +<a href="tts.html">tts</a> +module to generate speech. Your extension can then use any available +web technology to synthesize and output the speech, and send events back +to the calling function to report the status. +</p> + + +<h2 id="overview">Overview</h2> + +<p>An extension can register itself as a speech engine. By doing so, it +can intercept some or all calls to functions such as +<a href="tts.html#method-speak"><code>speak()</code></a> and +<a href="tts.html#method-stop"><code>stop()</code></a> +and provide an alternate implementation. +Extensions are free to use any available web technology +to provide speech, including streaming audio from a server, HTML5 audio, +Native Client, or Flash. An extension could even do something different +with the utterances, like display closed captions in a pop-up window or +send them as log messages to a remote server.</p> + +<h2 id="manifest">Manifest</h2> + +<p>To implement a TTS engine, an extension must +declare the "ttsEngine" permission and then declare all voices +it provides in the extension manifest, like this:</p> + +<pre>{ + "name": "My TTS Engine", + "version": "1.0", + <b>"permissions": ["ttsEngine"], + "tts_engine": { + "voices": [ + { + "voice_name": "Alice", + "lang": "en-US", + "gender": "female", + "event_types": ["start", "marker", "end"] + }, + { + "voice_name": "Pat", + "lang": "en-US", + "event_types": ["end"] + } + ] + },</b> + "background": { + "page": "background.html", + "persistent": false + } +}</pre> + +<p>An extension can specify any number of voices.</p> + +<p>The <code>voice_name</code> parameter is required. The name should be +descriptive enough that it identifies the name of the voice and the +engine used. In the unlikely event that two extensions register voices +with the same name, a client can specify the ID of the extension that +should do the synthesis.</p> + +<p>The <code>gender</code> parameter is optional. If your voice corresponds +to a male or female voice, you can use this parameter to help clients +choose the most appropriate voice for their application.</p> + +<p>The <code>lang</code> parameter is optional, but highly recommended. +Almost always, a voice can synthesize speech in just a single language. +When an engine supports more than one language, it can easily register a +separate voice for each language. Under rare circumstances where a single +voice can handle more than one language, it's easiest to just list two +separate voices and handle them using the same logic internally. However, +if you want to create a voice that will handle utterances in any language, +leave out the <code>lang</code> parameter from your extension's manifest.</p> + +<p>Finally, the <code>event_types</code> parameter is required if the engine can +send events to update the client on the progress of speech synthesis. +At a minimum, supporting the <code>'end'</code> event type to indicate +when speech is finished is highly recommended, otherwise Chrome cannot +schedule queued utterances.</p> + +<p class="note"> +<strong>Note:</strong> If your TTS engine does not support +the <code>'end'</code> event type, Chrome cannot queue utterances +because it has no way of knowing when your utterance has finished. To +help mitigate this, Chrome passes an additional boolean <code>enqueue</code> +option to your engine's onSpeak handler, giving you the option of +implementing your own queueing. This is discouraged because then +clients are unable to queue utterances that should get spoken by different +speech engines.</p> + +<p>The possible event types that you can send correspond to the event types +that the <code>speak()</code> method receives:</p> + +<ul> + <li><code>'start'</code>: The engine has started speaking the utterance. + <li><code>'word'</code>: A word boundary was reached. Use + <code>event.charIndex</code> to determine the current speech + position. + <li><code>'sentence'</code>: A sentence boundary was reached. Use + <code>event.charIndex</code> to determine the current speech + position. + <li><code>'marker'</code>: An SSML marker was reached. Use + <code>event.charIndex</code> to determine the current speech + position. + <li><code>'end'</code>: The engine has finished speaking the utterance. + <li><code>'error'</code>: An engine-specific error occurred and + this utterance cannot be spoken. + Pass more information in <code>event.errorMessage</code>. +</ul> + +<p>The <code>'interrupted'</code> and <code>'cancelled'</code> events are +not sent by the speech engine; they are generated automatically by Chrome.</p> + +<p>Text-to-speech clients can get the voice information from your +extension's manifest by calling +<a href="tts.html#method-getVoices">getVoices()</a>, +assuming you've registered speech event listeners as described below.</p> + +<h2 id="handling_speech_events">Handling speech events</h2> + +<p>To generate speech at the request of clients, your extension must +register listeners for both <code>onSpeak</code> and <code>onStop</code>, +like this:</p> + +<pre>var speakListener = function(utterance, options, sendTtsEvent) { + sendTtsEvent({'event_type': 'start', 'charIndex': 0}) + + // (start speaking) + + sendTtsEvent({'event_type': 'end', 'charIndex': utterance.length}) +}; + +var stopListener = function() { + // (stop all speech) +}; + +chrome.ttsEngine.onSpeak.addListener(speakListener); +chrome.ttsEngine.onStop.addListener(stopListener);</pre> + +<p class="warning"> +<b>Important:</b> +If your extension does not register listeners for both +<code>onSpeak</code> and <code>onStop</code>, it will not intercept any +speech calls, regardless of what is in the manifest.</p> + +<p>The decision of whether or not to send a given speech request to an +extension is based solely on whether the extension supports the given voice +parameters in its manifest and has registered listeners +for <code>onSpeak</code> and <code>onStop</code>. In other words, +there's no way for an extension to receive a speech request and +dynamically decide whether to handle it.</p> diff --git a/chrome/common/extensions/docs/templates/intros/types.html b/chrome/common/extensions/docs/templates/intros/types.html new file mode 100644 index 0000000..c2cf8b4 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/types.html @@ -0,0 +1,99 @@ +<p id="classSummary"> +The <code>chrome.types</code> module contains type declarations for Chrome. +Currently this comprises only a prototype for giving other +modules access to manage Chrome browser settings. This prototype is used, +for example, for <a + href="proxy.html#property-settings"><code>chrome.proxy.settings</code></a>. +</p> + +<h2 id="ChromeSetting">Chrome settings</h2> + +<p> +The <code>ChromeSetting</code> prototype provides a common set of functions +(<code>get()</code>, <code>set()</code>, and <code>clear()</code>) as +well as an event publisher (<code>onChange</code>) for settings of the +Chrome browser. The <a href="proxy.html#overview-examples">proxy settings + examples</a> demonstrate how these functions are intended to be used. +</p> + +<h3 id="ChromeSetting-lifecycle">Scope and life cycle</h3> + +<p> +Chrome distinguishes between three different scopes of browser settings: +<dl> + <dt><code>regular</code></dt> + <dd>Settings set in the <code>regular</code> scope apply to regular + browser windows and are inherited by incognito windows if they are not + overwritten. These settings are stored to disk and remain in place until + they are cleared by the governing extension, or the governing extension is + disabled or uninstalled.</dd> + + <dt><code>incognito_persistent</code></dt> + <dd>Settings set in the <code>incognito_persistent</code> scope apply only + to incognito windows. For these, they override <code>regular</code> + settings. These settings are stored to disk and remain in place until + they are cleared by the governing extension, or the governing extension is + disabled or uninstalled.</dd> + + <dt><code>incognito_session_only</code></dt> + <dd>Settings set in the <code>incognito_session_only</code> scope apply only + to incognito windows. For these, they override <code>regular</code> and + <code>incognito_session_only</code> settings. These settings are not + stored to disk and are cleared when the last incognito window is closed. They + can only be set when at least one incognito window is open.</dd> + +</dl> +</p> + +<h3 id="ChromeSetting-precedence">Precedence</h3> + +<p> +Chrome manages settings on different layers. The following list describes the +layers that may influence the effective settings, in increasing order of +precedence. +<ol> + <li>System settings provided by the operating system</li> + <li>Command-line parameters</li> + <li>Settings provided by extensions</li> + <li>Policies</li> +</ol> +</p> + +<p> +As the list implies, policies might overrule any changes that you specify with +your extension. You can use the <code>get()</code> function to determine whether +your extension is capable of providing a setting or whether this setting would +be overridden. +</p> + +<p> +As discussed above, Chrome allows using different settings for regular +windows and incognito windows. The following example illustrates the behavior. +Assume that no policy overrides the settings and that an extension can set +settings for regular windows <b>(R)</b> and settings for incognito windows +<b>(I)</b>. +</p> + +<p> +<ul> + <li>If only <b>(R)</b> is set, these settings are effective for both + regular and incognito windows.</li> + <li>If only <b>(I)</b> is set, these settings are effective for only + incognito windows. Regular windows use the settings determined by the lower + layers (command-line options and system settings).</li> + <li>If both <b>(R)</b> and <b>(I)</b> are set, the respective settings are + used for regular and incognito windows.</li> +</ul> +</p> + +<p> +If two or more extensions want to set the same setting to different values, +the extension installed most recently takes precedence over the other +extensions. If the most recently installed extension sets only <b>(I)</b>, the +settings of regular windows can be defined by previously installed extensions. +</p> + +<p> +The <em>effective</em> value of a setting is the one that results from +considering the precedence rules. It is used by Chrome. +<p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/webNavigation.html b/chrome/common/extensions/docs/templates/intros/webNavigation.html new file mode 100644 index 0000000..20afd95 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/webNavigation.html @@ -0,0 +1,169 @@ +<p id="classSummary"> +Use the <code>chrome.webNavigation</code> module to receive +notifications about the status of navigations requests in-flight. +</p> + +<h2>Manifest</h2> +<p> +All <code>chrome.webNavigation</code> methods and events require you to declare +the "webNavigation" permission in the <a href="manifest.html">extension +manifest</a>. +For example: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "webNavigation" + ]</b>, + ... +}</pre> + + +<h2>Examples</h2> + +<p> +You can find simple examples of using the tabs module in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/webNavigation/">examples/api/webNavigation</a> +directory. +For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p> + +<h2>Event order</h2> +<p> +For a navigation that is successfully completed, events are fired in the +following order: +<pre> +onBeforeNavigate -> onCommitted -> onDOMContentLoaded -> onCompleted +</pre> +</p> +<p> +Any error that occurs during the process results in an +<code>onErrorOccurred</code> event. For a specific navigation, there are no +further events fired after <code>onErrorOccurred</code>. +</p> +<p> +If a navigating frame contains subframes, its <code>onCommitted</code> is fired +before any of its children's <code>onBeforeNavigate</code>; while +<code>onCompleted</code> is fired after all of its children's +<code>onCompleted</code>. +</p> +<p> +If the reference fragment of a frame is changed, a +<code>onReferenceFragmentUpdated</code> event is fired. This event can fire any +time after <code>onDOMContentLoaded</code>, even after +<code>onCompleted</code>. +</p> +<p> +If the history API is used to modify the state of a frame (e.g. using +<code>history.pushState()</code>, a <code>onHistoryStateUpdated</code> event is +fired. This event can fire any time after <code>onDOMContentLoaded</code>. +</p> +<p> +If a navigation was triggered via <a +href="https://support.google.com/chrome/bin/answer.py?answer=177873">Chrome +Instant</a> or <a +href="https://support.google.com/chrome/bin/answer.py?answer=1385029">Instant +Pages</a>, a completely loaded page is swapped into the current tab. In that +case, an <code>onTabReplaced</code> event is fired. +</p> + +<h2>Relation to webRequest events</h2> +<p> +There is no defined ordering between events of the <a +href="webRequest.html">webRequest API</a> and the events of the +webNavigation API. It is possible that webRequest events are still received for +frames that already started a new navigation, or that a navigation only +proceeds after the network resources are already fully loaded. +</p> +<p> +In general, the webNavigation events are closely related to the navigation +state that is displayed in the UI, while the webRequest events correspond to +the state of the network stack which is generally opaque to the user. +</p> + +<h2>A note about tab IDs</h2> +<p> +Not all navigating tabs correspond to actual tabs in Chrome's UI, e.g., a tab +that is being pre-rendered. Such tabs are not accessible via the +<a href="tabs.html">tabs API</a> nor can you request information about them via +<code>webNavigation.getFrame</code> or <code>webNavigation.getAllFrames</code>. +Once such a tab is swapped in, an <code>onTabReplaced</code> event is fired and +they become accessible via these APIs. +</p> + +<h2>A note about timestamps</h2> +<p> +It's important to note that some technical oddities in the OS's handling +of distinct Chrome processes can cause the clock to be skewed between the +browser itself and extension processes. That means that WebNavigation's events' +<code>timeStamp</code> property is only guaranteed to be <i>internally</i> +consistent. Comparing one event to another event will give you the correct +offset between them, but comparing them to the current time inside the +extension (via <code>(new Date()).getTime()</code>, for instance) might give +unexpected results. +</p> + +<h2>A note about frame and process IDs</h2> +<p> +Due to the multi-process nature of Chrome, a tab might use different processes +to render the source and destination of a web page. Therefore, if a navigation +takes place in a new process, you might receive events both from the new and +the old page until the new navigation is committed (i.e. the +<code>onCommitted</code> event is send for the new main frame). Because frame +IDs are only unique for a given process, the webNavigation events include a +process ID, so you can still determine which frame a navigation came from. +</p> +<p> +Also note that during a provisional load the process might be switched several +times. This happens when the load is redirected to a different site. In this +case, you will receive repeated <code>onBeforeNavigate</code> and +<code>onErrorOccurred</code> events, until you receive the final +<code>onCommitted</code> event. +</p> + +<h2>Transition types and qualifiers</h2> +<p> +The webNavigation API's <code>onCommitted</code> event has a +<code>transitionType</code> and a <code>transitionQualifiers</code> property. +The <em>transition type</em> is the same as used in the <a +href="history.html#transition_types">history API</a> describing how the browser +navigated to this particular URL. In addition, several <em>transition +qualifiers</em> can be returned that further define the navigation. +</p> +<p> +The following transition qualifiers exist: +</p> +<table> +<tr> + <th> Transition qualifier </th> <th> Description </th> +</tr> +<tr> + <td>"client_redirect"</td> + <td> + One or more redirects caused by JavaScript or meta refresh tags on the page + happened during the navigation. + </td> +</tr> +<tr> + <td>"server_redirect"</td> + <td> + One or more redirects caused by HTTP headers sent from the server happened + during the navigation. + </td> +</tr> +<tr> + <td>"forward_back"</td> + <td> + The user used the Forward or Back button to initiate the navigation. + </td> +</tr> +<tr> + <td>"from_address_bar"</td> + <td> + The user initiated the navigation from the address bar (aka Omnibox). + </td> +</tr> +</table>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/webRequest.html b/chrome/common/extensions/docs/templates/intros/webRequest.html new file mode 100644 index 0000000..d5234af --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/webRequest.html @@ -0,0 +1,299 @@ +<p id="classSummary"> +Use the <code>chrome.webRequest</code> module to intercept, block, +or modify requests in-flight and to observe and analyze traffic. +</p> + +<h2 id="manifest">Manifest</h2> +<p>You must declare the "webRequest" permission in the <a + href="manifest.html">extension manifest</a> to use the web request +API, along with <a href="manifest.html#permissions">host permissions</a> +for any hosts whose network requests you want to access. If you want to +use the web request API in a blocking fashion, you need to request +the "webRequestBlocking" permission in addition. +For example:</p> +<pre>{ + "name": "My extension", + ... + <b>"permissions": [ + "webRequest", + "*://*.google.com" + ]</b>, + ... +}</pre> + +<h2 id="life_cycle">Life cycle of requests</h2> + +<p> +The web request API defines a set of events that follow the life cycle of a web +request. You can use these events to observe and analyze traffic. Certain +synchronous events will allow you to intercept, block, or modify a request. +</p> + +<p> +The event life cycle for successful requests is illustrated here, followed by +event definitions:<br/> +<img src="{{static}}/images/webrequestapi.png" + width="385" height="503" + alt="Life cycle of a web request from the perspective of the webrequest API" + style="margin-left: auto; margin-right: auto; display: block"/> +</p> + +<p> +<dl> + <dt><code>onBeforeRequest</code> (optionally synchronous)</dt> + <dd>Fires when a request is about to occur. This event is sent before any TCP + connection is made and can be used to cancel or redirect requests.</dd> + <dt><code>onBeforeSendHeaders</code> (optionally synchronous)</dt> + <dd>Fires when a request is about to occur and the initial headers have been + prepared. The event is intended to allow extensions to add, modify, and delete + request headers <a href="#life_cycle_footnote">(*)</a>. The + <code>onBeforeSendHeaders</code> event is passed to all subscribers, so + different subscribers may attempt to modify the request; see the <a + href="#implementation">Implementation details</a> section for how this is + handled. This event can be used to cancel the request.</dd> + <dt><code>onSendHeaders</code></dt> + <dd>Fires after all extensions have had a chance to modify the request + headers, and presents the final <a href="#life_cycle_footnote">(*)</a> + version. The event is triggered before the headers are sent to the network. + This event is informational and handled asynchronously. It does not allow + modifying or cancelling the request.</dd> + <dt><code>onHeadersReceived</code> (optionally synchronous)</dt> + <dd>Fires each time that an HTTP(S) response header is received. Due + to redirects and authentication requests this can happen multiple times per + request. This event is intended to allow extensions to add, modify, and delete + response headers, such as incoming Set-Cookie headers.</dd> + <dt><code>onAuthRequired</code> (optionally synchronous)</dt> + <dd>Fires when a request requires authentication of the user. This event can + be handled synchronously to provide authentication credentials. Note that + extensions may provide invalid credentials. Take care not to enter an infinite + loop by repeatedly providing invalid credentials.</dd> + <dt><code>onBeforeRedirect</code></dt> + <dd>Fires when a redirect is about to be executed. A redirection can be + triggered by an HTTP response code or by an extension. This event is + informational and handled asynchronously. It does not allow you to modify or + cancel the request. </dd> + <dt><code>onResponseStarted</code></dt> + <dd>Fires when the first byte of the response body is received. For HTTP + requests, this means that the status line and response headers are + available. This event is informational and handled asynchronously. It does not + allow modifying or cancelling the request.</dd> + <dt><code>onCompleted</code></dt> + <dd>Fires when a request has been processed successfully.</dd> + <dt><code>onErrorOccurred</code></dt> + <dd>Fires when a request could not be processed successfully.</dd> +</dl> +The web request API guarantees that for each request either +<code>onCompleted</code> or <code>onErrorOccurred</code> is fired as the final +event with one exception: If a request is redirected to a <code>data://</code> +URL, <code>onBeforeRedirect</code> is the last reported event. +</p> + +<p id="life_cycle_footnote">(*) Note that the web request API presents an +abstraction of the network stack to the extension. Internally, one URL request +can be split into several HTTP requests (for example to fetch individual byte +ranges from a large file) or can be handled by the network stack without +communicating with the network. For this reason, the API does not provide the +final HTTP headers that are sent to the network. For example, all headers that +are related to caching are invisible to the extension.</p> + +<p>The following headers are currently <b>not provided</b> to the +<code>onBeforeSendHeaders</code> event. This list is not guaranteed to be +complete nor stable. +<ul> + <li>Authorization</li> + <li>Cache-Control</li> + <li>Connection</li> + <li>Content-Length</li> + <li>Host</li> + <li>If-Modified-Since</li> + <li>If-None-Match</li> + <li>If-Range</li> + <li>Partial-Data</li> + <li>Pragma</li> + <li>Proxy-Authorization</li> + <li>Proxy-Connection</li> + <li>Transfer-Encoding</li> +</ul> +</p> + +<p> +The webRequest API only exposes requests that the extension has +permission to see, given its +<a href="manifest.html#permissions">host permissions</a>. +Moreover, only the following schemes are accessible: +<code>http://</code>, +<code>https://</code>, +<code>ftp://</code>, +<code>file://</code>, or +<code>chrome-extension://</code>. +In addition, even certain requests with URLs using one of the above schemes +are hidden, e.g., +<code>chrome-extension://other_extension_id</code> where +<code>other_extension_id</code> is not the ID of the extension to handle +the request, +<code>https://www.google.com/chrome</code>, +and others (this list is not complete). Also synchronous XMLHttpRequests from +your extension are hidden from blocking event handlers in order to prevent +deadlocks. +</p> + +<h2 id="concepts">Concepts</h2> + +<p>As the following sections explain, events in the web request API use request +IDs, and you can optionally specify filters and extra information when you +register event listeners.</p> + +<h3 id="Request IDs">Request IDs</h3> + +<p>Each request is identified by a request ID. This ID is unique within a +browser session and the context of an extension. It remains constant during the +the life cycle of a request and can be used to match events for the same +request. Note that several HTTP requests are mapped to one web request in case +of HTTP redirection or HTTP authentication.</p> + +<h3 id="subscription">Registering event listeners</h3> + +<p>To register an event listener for a web request, you use a variation on the +<a href="events.html">usual <code>addListener()</code> function</a>. +In addition to specifying a callback function, +you have to specify a filter argument and you may specify an optional extra info +argument.</p> + +<p>The three arguments to the web request API's <code>addListener()</code> have +the following definitions:</p> +<pre> +var callback = function(details) {...}; +var filter = {...}; +var opt_extraInfoSpec = [...]; +</pre> + +<p>Here's an example of listening for the <code>onBeforeRequest</code> +event:</p> +<pre> +chrome.webRequest.onBeforeRequest.addListener( + callback, filter, opt_extraInfoSpec); +</pre> + +<p>Each <code>addListener()</code> call takes a mandatory callback function as +the first parameter. This callback function is passed a dictionary containing +information about the current URL request. The information in this dictionary +depends on the specific event type as well as the content of +<code>opt_extraInfoSpec</code>.</p> + +<p>If the optional <code>opt_extraInfoSpec</code> array contains the string +<code>'blocking'</code> (only allowed for specific events), the callback +function is handled synchronously. That means that the request is blocked until +the callback function returns. In this case, the callback can return a <a + href="#type-BlockingResponse">BlockingResponse</a> that determines the further +life cycle of the request. Depending on the context, this response allows +cancelling or redirecting a request (<code>onBeforeRequest</code>), cancelling a +request or modifying headers (<code>onBeforeSendHeaders</code>, +<code>onHeadersReceived</code>), or providing authentication credentials +(<code>onAuthRequired</code>).</p> + +<p>The <a href="#type-RequestFilter">RequestFilter</a> +<code>filter</code> allows limiting the requests for which events are +triggered in various dimensions: +<dl> + <dt>URLs</dt> + <dd><a href="match_patterns.html">URL patterns</a> such as + <code>*://www.google.com/foo*bar</code>.</dd> + <dt>Types</dt> + <dd>Request types such as <code>main_frame</code> (a document that is loaded + for a top-level frame), <code>sub_frame</code> (a document that is loaded for + an embedded frame), and <code>image</code> (an image on a web site). + See <a href="#type-RequestFilter">RequestFilter</a>.</dd> + <dt>Tab ID</dt> + <dd>The identifier for one tab.</dd> + <dt>Window ID</dt> + <dd>The identifier for a window.</dd> +</p> + +<p>Depending on the event type, you can specify strings in +<code>opt_extraInfoSpec</code> to ask for additional information about the +request. This is used to provide detailed information on request's data only +if explicitly requested.</p> + +<h2 id="implementation">Implementation details</h2> + +<p>Several implementation details can be important to understand when developing +an extension that uses the web request API:</p> + +<h3>Conflict resolution</h3> +<p>In the current implementation of the web request API, a request is considered +as cancelled if at least one extension instructs to cancel the request. If +an extension cancels a request, all extensions are notified by an +<code>onErrorOccurred</code> event. Only one extension is allowed to redirect a +request or modify a header at a time. If more than one extension attempts to +modify the request, the most recently installed extension wins and all others +are ignored. An extension is not notified if its instruction to modify or +redirect has been ignored.</p> + +<h3>Caching</h3> +<p> +Chrome employs two caches — an on-disk cache and a very fast in-memory +cache. The lifetime of an in-memory cache is attached to the lifetime of a +render process, which roughly corresponds to a tab. Requests that are answered +from the in-memory cache are invisible to the web request API. If a request +handler changes its behavior (for example, the behavior according to which +requests are blocked), a simple page refresh might not respect this changed +behavior. To make sure the behavior change goes through, call +<code>handlerBehaviorChanged()</code> to flush the in-memory cache. But don't do +it often; flushing the cache is a very expensive operation. You don't need to +call <code>handlerBehaviorChanged()</code> after registering or unregistering an +event listener.</p> + +<h3>Timestamps</h3> +<p> +The <code>timestamp</code> property of web request events is only guaranteed to +be <i>internally</i> consistent. Comparing one event to another event will give +you the correct offset between them, but comparing them to the current time +inside the extension (via <code>(new Date()).getTime()</code>, for instance) +might give unexpected results. +</p> + +<h2 id="examples">Examples</h2> + +<p>The following example illustrates how to block all requests to +<code>www.evil.com</code>:</p> +<pre> +chrome.webRequest.onBeforeRequest.addListener( + function(details) { + return {cancel: details.url.indexOf("://www.evil.com/") != -1}; + }, + {urls: ["<all_urls>"]}, + ["blocking"]); +</pre> + +<p>As this function uses a blocking event handler, it requires the "webRequest" +as well as the "webRequestBlocking" permission in the manifest file.</p> + +<p>The following example achieves the same goal in a more efficient way because +requests that are not targeted to <code>www.evil.com</code> do not need to be +passed to the extension:</p> +<pre> +chrome.webRequest.onBeforeRequest.addListener( + function(details) { return {cancel: true}; }, + {urls: ["*://www.evil.com/*"]}, + ["blocking"]); +</pre> + +<p>The following example illustrates how to delete the User-Agent header from +all requests:</p> +<pre> +chrome.webRequest.onBeforeSendHeaders.addListener( + function(details) { + for (var i = 0; i < details.requestHeaders.length; ++i) { + if (details.requestHeaders[i].name === 'User-Agent') { + details.requestHeaders.splice(i, 1); + break; + } + } + return {requestHeaders: details.requestHeaders}; + }, + {urls: ["<all_urls>"]}, + ["blocking", "requestHeaders"]); +</pre> + +<p> For more example code, see the <a href="samples.html#webrequest">web request +samples</a>.</p>
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/intros/windows.html b/chrome/common/extensions/docs/templates/intros/windows.html new file mode 100644 index 0000000..2b38b65 --- /dev/null +++ b/chrome/common/extensions/docs/templates/intros/windows.html @@ -0,0 +1,69 @@ +<p id="classSummary"> +Use the <code>chrome.windows</code> module +to interact with browser windows. +You can use this module to +create, modify, and rearrange windows in the browser. +</p> + +<img src="{{static}}/images/windows.png" + width="256" height="76" alt="Two windows, each with one tab" /> + +<h2 id="manifest">Manifest</h2> +<p> +To use the windows API, +you must declare the "tabs" permission +in <a href="manifest.html">manifest.json</a>. +(No, that isn't a typo — +the window and tabs modules interact so closely we +decided to just share one permission between them.) +For example: +</p> + +<pre>{ + "name": "My extension", + ... + <b>"permissions": ["tabs"]</b>, + ... +}</pre> + +<h2 id="current-window">The current window</h2> + +<p>Many functions in the extension system +take an optional <var>windowId</var> parameter, +which defaults to the current window. +</p> + +<p>The <em>current window</em> is the window that +contains the code that is currently executing. +It's important to realize that this can be +different from the topmost or focused window. +</p> + +<p>For example, say an extension +creates a few tabs or windows from a single HTML file, +and that the HTML file +contains a call to +<a href="tabs.html#method-getSelected">chrome.tabs.getSelected</a>. +The current window is the window that contains the page that made +the call, no matter what the topmost window is. +</p> + +<p>In the case of the <a href="event_pages.html">event page</a>, +the value of the current window falls back to the last active window. Under some +circumstances, there may be no current window for background pages. +</p> + +<h2 id="examples"> Examples </h2> + +<p> +You can find simple examples of using the windows module in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/windows/">examples/api/windows</a> +directory. +Another example is in the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/inspector/tabs_api.html?content-type=text/plain">tabs_api.html</a> file +of the +<a href="http://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/extensions/docs/examples/api/tabs/inspector/">inspector</a> +example. +For other examples and for help in viewing the source code, see +<a href="samples.html">Samples</a>. +</p> diff --git a/chrome/common/extensions/docs/templates/private/api_property.html b/chrome/common/extensions/docs/templates/private/api_property.html new file mode 100644 index 0000000..2bd48b0 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/api_property.html @@ -0,0 +1,15 @@ +<div> + <a name="property-{{name}}"></a> + <h4>{{name}}</h4> + <div class="summary"> + <span>chrome.{{api.name}}.{{name}}</span> + </div> + <div> + <dt><span class="property">{{name}}</span> {{+partials.type_name}}</dt> + {{?description}}<dd> + {{{description}}} + </dd>{{/description}} + <dd><dl>{{#properties}}{{+partials.property}}{{/}}</dl></dd> + <dd><dl>{{#functions}}{{+partials.function}}{{/}}</dl></dd> + </div> +</div> diff --git a/chrome/common/extensions/docs/templates/private/api_reference.html b/chrome/common/extensions/docs/templates/private/api_reference.html new file mode 100644 index 0000000..a9580e2 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/api_reference.html @@ -0,0 +1,38 @@ +<a name="apiReference"></a> +<h2>API Reference: chrome.{{api.name}}</h2> +<div class="api_reference"> + {{?api.types}} + <h3 id="types">Types</h3> + {{#api.types}} + {{+partials.type api:api type:@}} + {{/}} + {{/api.types}} + {{?api.properties}} + <h3 id="properties">Properties</h3> + {{#api.properties}} + {{+partials.api_property api:api}} + {{/}} + {{/api.properties}} + {{?api.functions}} + <h3 id="methods">Methods</h3> + {{#api.functions}} + {{+partials.function api:api}} + {{/}} + {{/api.functions}} + {{?api.events}} + <h3 id="events">Events</h3> + {{#api.events}} + {{+partials.event api:api}} + {{/}} + {{/api.events}} +</div> +{{?samples_list}} + <a name="samples"></a> + <h2>Sample {{title}} that use chrome.{{api.name}}</h2> + {{#samples_list}} + <li><strong><a href="samples.html#{{id}}">{{name}}</a></strong> – + {{?description}} + {{description}} + {{/description}}</li> + {{/samples_list}} +{{/samples_list}} diff --git a/chrome/common/extensions/docs/templates/private/apps_footer.html b/chrome/common/extensions/docs/templates/private/apps_footer.html new file mode 100644 index 0000000..f997b85 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/apps_footer.html @@ -0,0 +1,8 @@ +<script> + window.bootstrap = { + api_names: {{*api_list.apps.chrome}}.concat( + {{*api_list.apps.experimental}}), + branchInfo: {{*branchInfo}} + }; +</script> +{{+partials.footer}} diff --git a/chrome/common/extensions/docs/templates/private/apps_sidenav.html b/chrome/common/extensions/docs/templates/private/apps_sidenav.html new file mode 100644 index 0000000..9ff2b87 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/apps_sidenav.html @@ -0,0 +1,53 @@ +<div class="g-unit g-first" id="gc-sidebar"> + <ul> + <li><span>Getting Started</span> + <ul> + <li><a href="about_apps.html">What Are Packaged Apps?</a></li> + <li><a href="app_architecture.html">Understand the Architecture</a></li> + <li><a href="first_app.html">Create Your First App</a></li> + </ul> + </li> + <li><span>Developing</span> + <ul> + <li><a href="develop_apps.html">Before You Start</a></li> + <li><span>The Fundamentals</span> + <ul toggleable> + <li><a href="app_lifecycle.html">Manage App Lifecycle</a></li> + <li><a href="app_storage.html">Manage Data</a></li> + <li><a href="offline_apps.html">Offline First</a></li> + <li><a href="app_external.html">Embed Content</a></li> + </ul> + </li> + <li><span>Security & Privacy</span> + <ul toggleable> + <li><a href="app_identity.html">Identify User</a></li> + <li><a href="app_csp.html">Comply with CSP</a></li> + </ul> + </li> + <li><span>Advanced Technologies</span> + <ul toggleable> + <li><a href="app_network.html">Network Communications</a></li> + <li><a href="app_hardware.html">Access Hardware Devices</a></li> + <li><a href="app_intents.html">Connect Apps with Web Intents</a></li> + </ul> + </li> + <li><a href="app_frameworks.html">MVC Architecture</a></li> + </ul> + </li> + <li><span>Deploying</span> + <ul> + <li><a href="publish_app.html">Publish</a></li> + </ul> + </li> + <li><span>Reference</span> + <ul> + <li><a href="manifest.html">Manifest Files</a></li> + <li><a href="api_index.html">Chrome JavaScript APIs</a></li> + <li><a href="api_other.html">Supported Libraries</a></li> + <li><a href="app_deprecated.html">Disabled Web Features</a></li> + </ul> + </li> + <li><span><a href="samples.html">Samples</a></span></li> + <li><span><a href="app_known_issues.html">Known Issues</a></span></li> + </ul> +</div> diff --git a/chrome/common/extensions/docs/templates/private/callback.html b/chrome/common/extensions/docs/templates/private/callback.html new file mode 100644 index 0000000..c6a52bc --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/callback.html @@ -0,0 +1,14 @@ +<h4>Callback function</h4> +<p> + {{?optional}} + If you specify the <em>{{name}}</em> parameter, it should + specify a function that looks like this: + {{:}} + The <em>{{name}}</em> parameter should specify a function + that looks like this: + {{/}} +</p> +<pre>function({{#parameters}}{{+partials.variable_type}} {{name}}{{^last}}, {{/}}{{/}}) <span class="subdued">{...}</span>;</pre> +<dl> + {{#parameters}}{{+partials.parameter_full}}{{/}} +</dl> diff --git a/chrome/common/extensions/docs/templates/private/event.html b/chrome/common/extensions/docs/templates/private/event.html new file mode 100644 index 0000000..639f35c --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/event.html @@ -0,0 +1,39 @@ +<div> + <a name="event-{{?prefix}}{{prefix}}-{{/}}{{name}}"></a> + <h4>{{name}}</h4> + <div class="summary"> + <span class="subdued">{{?prefix}}{{prefix}}{{:}}chrome.{{api.name}}{{/}}.</span>{{name}}<span class="subdued">.addListener</span>(function({{#parameters}}{{+partials.parameter_item}}{{^last}}, {{/}}{{/}})<span class="subdued"> {...}</span>); + </div> + <div class="description"> + {{?description}}<p> + {{{description}}} + </p>{{/description}} + {{?supportsRules}} + <p>See <a href="events.html#method-Event-addRules"><code>chrome.events.Event.addRules()</code></a>.</p> + {{/supportsRules}} + {{?conditions}} + <h4>Supported conditions</h4> + <dl> + {{#conditions}}<div><dt>{{+partials.ref_link}}</dt></div>{{/}} + </dl> + {{/conditions}} + {{?actions}} + <h4>Supported actions</h4> + <dl> + {{#actions}}<div><dt>{{+partials.ref_link}}</dt></div>{{/}} + </dl> + {{/actions}} + {{?parameters}} + <h4>Listener Parameters</h4> + <dl> + {{#parameters}}{{+partials.parameter_full}}{{/}} + </dl> + {{/parameters}} + {{?filters}} + <h4>Filters</h4> + <dl> + {{#filters}}{{+partials.parameter_full}}{{/}} + </dl> + {{/filters}} + </div> +</div> diff --git a/chrome/common/extensions/docs/templates/private/extensions_footer.html b/chrome/common/extensions/docs/templates/private/extensions_footer.html new file mode 100644 index 0000000..14d498a --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/extensions_footer.html @@ -0,0 +1,8 @@ +<script> + window.bootstrap = { + api_names: {{*api_list.extensions.chrome}}.concat( + {{*api_list.extensions.experimental}}), + branchInfo: {{*branchInfo}} + }; +</script> +{{+partials.footer}} diff --git a/chrome/common/extensions/docs/templates/private/extensions_sidenav.html b/chrome/common/extensions/docs/templates/private/extensions_sidenav.html new file mode 100644 index 0000000..4e4a79b --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/extensions_sidenav.html @@ -0,0 +1,80 @@ +<div class="g-unit g-first" id="gc-sidebar"> + <ul> + <li><a href="getstarted.html">Getting Started</a></li> + <li><a href="overview.html">Overview</a></li> + <li><a href="whats_new.html">What's New?</a></li> + <li><a href="devguide.html">Developer's Guide</a> + <ul> + <li><span>Browser UI</span> + <ul toggleable> + <li><a href="browserAction.html">Browser Actions</a></li> + <li><a href="contextMenus.html">Context Menus</a></li> + <li><a href="notifications.html">Desktop Notifications</a></li> + <li><a href="omnibox.html">Omnibox</a></li> + <li><a href="options.html">Options Pages</a></li> + <li><a href="override.html">Override Pages</a></li> + <li><a href="pageAction.html">Page Actions</a></li> + </ul> + </li> + <li><span>Browser Interaction</span> + <ul toggleable> + <li><a href="bookmarks.html">Bookmarks</a></li> + <li><a href="cookies.html">Cookies</a></li> + <li><a href="devtools.html">Developer Tools</a></li> + <li><a href="events.html">Events</a></li> + <li><a href="history.html">History</a></li> + <li><a href="management.html">Management</a></li> + <li><a href="tabs.html">Tabs</a></li> + <li><a href="windows.html">Windows</a></li> + </ul> + </li> + <li><span>Implementation</span> + <ul toggleable> + <li><a href="a11y.html">Accessibility</a></li> + <li><a href="event_pages.html">Event Pages</a></li> + <li><a href="content_scripts.html">Content Scripts</a></li> + <li><a href="xhr.html">Cross-Origin XHR</a></li> + <li><a href="i18n.html">Internationalization</a></li> + <li><a href="messaging.html">Message Passing</a></li> + <li><a href="permissions.html">Optional Permissions</a></li> + <li><a href="npapi.html">NPAPI Plugins</a></li> + </ul> + </li> + <li><span>Finishing</span> + <ul toggleable> + <li><a href="hosting.html">Hosting</a></li> + <li><a href="external_extensions.html">Other Deployment Options</a></li> + </ul> + </li> + </ul> + </li> + <li><a href="tutorials.html">Tutorials</a> + <ul> + <li><a href="tut_migration_to_manifest_v2.html">Manifest V2</a></li> + <li><a href="tut_debugging.html">Debugging</a></li> + <li><a href="tut_analytics.html">Google Analytics</a></li> + <li><a href="tut_oauth.html">OAuth</a></li> + </ul> + </li> + <li><span>Reference</span> + <ul> + <li><span>Formats</span> + <ul toggleable> + <li><a href="manifest.html">Manifest Files</a></li> + <li><a href="match_patterns.html">Match Patterns</a></li> + </ul> + </li> + <li><a href="permission_warnings.html">Permission Warnings</a></li> + <li><a href="api_index.html">chrome.* APIs</a></li> + <li><a href="api_other.html">Other APIs</a></li> + </ul> + </li> + <li><span>More</span> + <ul> + <li><a href="http://code.google.com/chrome/webstore/docs/index.html">Chrome Web Store</a></li> + <li><a href="http://code.google.com/chrome/apps/docs/developers_guide.html">Hosted Apps</a></li> + <li><a href="themes.html">Themes</a></li> + </ul> + </li> + </ul> +</div> diff --git a/chrome/common/extensions/docs/templates/private/filter_item.html b/chrome/common/extensions/docs/templates/private/filter_item.html new file mode 100644 index 0000000..570feaf --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/filter_item.html @@ -0,0 +1 @@ +<span><a href="javascript:void(0)">{{name}}</a>{{^last}} | {{/}}</span> diff --git a/chrome/common/extensions/docs/templates/private/footer.html b/chrome/common/extensions/docs/templates/private/footer.html new file mode 100644 index 0000000..8501191 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/footer.html @@ -0,0 +1,56 @@ +<div id="gc-footer"> + <div class="text"> + <p> + Except as otherwise <a href="http://code.google.com/policies.html#restrictions">noted</a>, + the content of this page is licensed under the <a rel="license" href="http://creativecommons.org/licenses/by/3.0/">Creative Commons + Attribution 3.0 License</a>, and code samples are licensed under the + <a rel="license" href="http://code.google.com/google_bsd_license.html">BSD License</a>. + </p> + <p> + ©2012 Google + </p> + <script src="{{static}}/js/branch.js" type="text/javascript"></script> + <script src="{{static}}/js/sidebar.js" type="text/javascript"></script> + <script src="{{static}}/js/prettify.js" type="text/javascript"></script> + <script> + (function() { + // Auto syntax highlight all pre tags. + var preElements = document.getElementsByTagName('pre'); + for (var i = 0; i < preElements.length; i++) + preElements[i].classList.add('prettyprint'); + prettyPrint(); + })(); + </script> + <script src="https://www.google-analytics.com/urchin.js" type="text/javascript"></script> + <script src="https://www.google-analytics.com/ga.js" type="text/javascript"></script> + <script type="text/javascript"> + // chrome doc tracking + try { + var engdocs = _gat._getTracker("YT-10763712-2"); + engdocs._trackPageview(); + } catch(err) {} + // code.google.com site-wide tracking + try { + _uacct="UA-18071-1"; + _uanchor=1; + _uff=0; + urchinTracker(); + } + catch(e) {/* urchinTracker not available. */} + </script> + <script src="http://www.google.com/jsapi" type="text/javascript"></script> + <script type="text/javascript"> + google.load('search', '1', + {language : 'en', style : google.loader.themes.V2_DEFAULT}); + google.setOnLoadCallback(function() { + var customSearchOptions = {}; + var customSearchControl = new google.search.CustomSearchControl( + '002967670403910741006:61_cvzfqtno', customSearchOptions); + customSearchControl.setResultSetSize( + google.search.Search.FILTERED_CSE_RESULTSET); + customSearchControl.draw('cse'); + }, true); + </script> + <script type="text/javascript">google.load("elements", "1", {packages: "transliteration"});</script> + </div> +</div> diff --git a/chrome/common/extensions/docs/templates/private/function.html b/chrome/common/extensions/docs/templates/private/function.html new file mode 100644 index 0000000..c6e65a1 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/function.html @@ -0,0 +1,19 @@ +<div> + <a name="method-{{?prefix}}{{prefix}}-{{/}}{{name}}"></a> + <h4>{{name}}</h4> + <div class="summary{{^returns}} lower{{/}}"> + <span>{{?returns}}{{+partials.variable_type}} {{/}}{{?prefix}}{{prefix}}{{:}}chrome.{{api.name}}{{/}}.{{name}}</span>({{#parameters}}{{+partials.parameter_item}}{{^last}}, {{/}}{{/}}) + </div> + <div class="description"> + {{?description}}<p> + {{{description}}} + </p>{{/description}} + {{?parameters}} + <h4>Parameters</h4> + <dl> + {{#parameters}}{{+partials.parameter_full}}{{/}} + </dl> + {{?callback}}{{+partials.callback}}{{/}} + {{/parameters}} + </div> +</div> diff --git a/chrome/common/extensions/docs/templates/private/header_body.html b/chrome/common/extensions/docs/templates/private/header_body.html new file mode 100644 index 0000000..71d35ee --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/header_body.html @@ -0,0 +1,42 @@ +{{?branchInfo.showWarning}} +<div id="branchWarning" class="displayModeWarning"> + <span>WARNING: this is the {{branchInfo.current}} documentation. It may not work with the stable release of Chrome.</span> + <select id="branchChooser"> + <option value="">Choose a different version...</option> + {{#branchInfo.channels}} + <option value="{{path}}">{{name}}</option> + {{/}} + </select> +</div> +{{/}} +<a id="top"></a> +<div id="header"> + <span id="logo"> + <a href="http://code.google.com/"><img src="{{static}}/images/chrome_logo.gif" alt="Google Code Labs"></a> + </span> + <span id="cse"></span> +</div> +<a id="gc-topnav-anchor"></a> +<div id="gc-topnav"> + <h1>Google Chrome {{title}}</h1> + <ul id="home" class="gc-topnav-tabs"> + <li id="home_link"> + <a href="index.html" title="Google Chrome {{title}} home page"><div>Home</div></a> + </li> + <li id="docs_link"> + <a href="docs.html" title="Official Google Chrome {{title}} documentation"><div>Docs</div></a> + </li> + <li id="faq_link"> + <a href="faq.html" title="Answers to frequently asked questions about Google Chrome {{title}}"><div>FAQ</div></a> + </li> + <li id="samples_link"> + <a href="samples.html" title="Sample {{title}} (with source code)"><div>Samples</div></a> + </li> + <li id="group_link"> + <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions" title="Google Chrome {{title}} developer forum"><div>Group</div></a> + </li> + <li id="so_link"> + <a href="http://stackoverflow.com/questions/tagged/google-chrome-extension" title="[google-chrome-extension] tag on Stack Overflow"><div>Questions?</div></a> + </li> + </ul> +</div> diff --git a/chrome/common/extensions/docs/templates/private/header_head.html b/chrome/common/extensions/docs/templates/private/header_head.html new file mode 100644 index 0000000..bc43325 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/header_head.html @@ -0,0 +1,5 @@ +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<link href="{{static}}/css/site.css" rel="stylesheet" type="text/css"> +<link href="{{static}}/css/print.css" rel="stylesheet" type="text/css" media="print"> +<link href="{{static}}/css/prettify.css" rel="stylesheet" type="text/css"> +<link href="//www.google.com/images/icons/product/chrome-16.png" rel="icon" type="image/ico"> diff --git a/chrome/common/extensions/docs/templates/private/parameter_full.html b/chrome/common/extensions/docs/templates/private/parameter_full.html new file mode 100644 index 0000000..245c122 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/parameter_full.html @@ -0,0 +1,12 @@ +<div> + {{+partials.property}} + {{?properties}} + <dd> + <dl> + {{#properties}} + {{^additional_properties}}{{+partials.property}}{{/}} + {{/}} + </dl> + </dd> + {{/properties}} +</div> diff --git a/chrome/common/extensions/docs/templates/private/parameter_item.html b/chrome/common/extensions/docs/templates/private/parameter_item.html new file mode 100644 index 0000000..8214388 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/parameter_item.html @@ -0,0 +1 @@ +<span{{?optional}} class="optional"{{/}}>{{+partials.variable_type}} <span class="variable">{{name}}</span></span> diff --git a/chrome/common/extensions/docs/templates/private/property.html b/chrome/common/extensions/docs/templates/private/property.html new file mode 100644 index 0000000..843ea55 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/property.html @@ -0,0 +1,12 @@ +<dt> + <span class="variable">{{name}}</span> + <span class="property"> + ( + {{?optional}}<span class="optional">optional</span>{{/}} + <span id="typeTemplate">{{+partials.variable_type}}</span> + ) + </span> +</dt> +{{?description}}<dd> + {{{description}}} +</dd>{{/description}} diff --git a/chrome/common/extensions/docs/templates/private/ref_link.html b/chrome/common/extensions/docs/templates/private/ref_link.html new file mode 100644 index 0000000..58873ef --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/ref_link.html @@ -0,0 +1 @@ +<a href="{{href}}">{{text}}</a> diff --git a/chrome/common/extensions/docs/templates/private/sample_item.html b/chrome/common/extensions/docs/templates/private/sample_item.html new file mode 100644 index 0000000..a6ba282 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/sample_item.html @@ -0,0 +1,24 @@ +<div class="sample" tags="{{#api_calls}}{{name}} {{/}}"> + <a name="{{id}}"></a> + <img class="icon" src="{{icon}}"> + <h2><a href="{{download_url}}">{{name}}</a></h2> + {{?description}} + {{description}} + {{/description}} + <div> + <span class="label">Calls:</span> + <ul> + {{#api_calls}} + <li><code><a href="{{link}}">{{name}}</a></code></li> + {{/}} + </ul> + </div> + <div> + <span class="label">Source Files:</span> + <ul> + {{#files}} + <li><code><a href="{{url}}/{{@}}">{{@}}</a></code></li> + {{/}} + </ul> + </div> +</div> diff --git a/chrome/common/extensions/docs/templates/private/samples.html b/chrome/common/extensions/docs/templates/private/samples.html new file mode 100644 index 0000000..5f97504 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/samples.html @@ -0,0 +1,40 @@ +{{- sidenav: the sidenav bar for either apps or extensions -}} +{{- filter_list: the list of APIs that show up in the filter box -}} +{{- samples_list: the list of samples shown on the page -}} +{{- footer: the footer for either apps or extensions -}} +<!DOCTYPE html> +<html> + <head> + {{+partials.header_head}} + <link href="{{static}}/css/samples.css" rel="stylesheet" type="text/css"> + <title>Sample {{title}} - Google Chrome {{title}}</title> + </head> + <body> + {{+partials.header_body}} + <div id="gc-container"> + {{+sidenav}} + <div id="gc-pagecontent"> + <h1 class="page_title">Sample {{title}}</h1> + <div id="controls"> + <table class="controlbox"> + <tr> + <td class="label">Filter by keyword:</td> + <td><input autofocus type="search" id="search_input" placeholder="Type to search"></td> + </tr> + <tr> + <td class="label">Filter by API:</td> + <td> + <div id="api_filter_items"> + {{#filter_list}}{{+partials.filter_item}}{{/}} + </div> + </td> + </tr> + </table> + </div> + {{#samples_list}}{{+partials.sample_item}}{{/}} + </div> + </div> + </body> + {{+footer}} + <script src="{{static}}/js/samples.js" type="text/javascript"></script> +</html> diff --git a/chrome/common/extensions/docs/templates/private/standard_apps_api.html b/chrome/common/extensions/docs/templates/private/standard_apps_api.html new file mode 100644 index 0000000..a302775 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/standard_apps_api.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> + <head> + {{+partials.header_head}} + <link href="{{static}}/css/api.css" rel="stylesheet" type="text/css"> + {{+partials.title}} + </head> + <body> + {{+partials.header_body title:apps_title}} + <div id="gc-container"> + {{+partials.apps_sidenav}} + <div id="gc-pagecontent"> + <h1 class="page_title">chrome.{{api.name}}</h1> + {{?api.permissions.dev}}{{+partials.warning_dev}}{{/}} + {{?api.permissions.beta}}{{+partials.warning_beta}}{{/}} + {{?intro.toc}} + {{+partials.table_of_contents toc_items:intro.toc + has_toc:true + api:api + samples_list:api.samples.apps + title:apps_title}} + {{:intro.toc}} + {{+partials.table_of_contents has_toc:false + api:api + samples_list:api.samples.apps + title:apps_title}} + {{/intro.toc}} +{{- This is unindented because it contains <pre> tags -}} +{{?intro}} +{{+intro.intro is_apps:true}} +{{/intro}} + {{+partials.api_reference samples_list:api.samples.apps + title:apps_title}} + </div> + </div> + </body> + {{+partials.apps_footer}} +</html> diff --git a/chrome/common/extensions/docs/templates/private/standard_apps_article.html b/chrome/common/extensions/docs/templates/private/standard_apps_article.html new file mode 100644 index 0000000..3509d34 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/standard_apps_article.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> + <head> + {{+partials.header_head}} + <title>{{article.title}} - Google Chrome</title> + </head> + <body> + {{+partials.header_body title:apps_title}} + <div id="gc-container"> + {{+partials.apps_sidenav}} + <div id="gc-pagecontent"> + <h1 class="page_title">{{article.title}}</h1> + {{?article.toc}} + {{+partials.table_of_contents toc_items:article.toc + has_toc:true + title:apps_title}} + {{/article.toc}} +{{- This may contain <pre> tags so it is not indented -}} +{{+article.intro is_apps:true}} + </div> + </div> + </body> + {{+partials.apps_footer}} +</html> diff --git a/chrome/common/extensions/docs/templates/private/standard_extensions_api.html b/chrome/common/extensions/docs/templates/private/standard_extensions_api.html new file mode 100644 index 0000000..3703bad --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/standard_extensions_api.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> + <head> + {{+partials.header_head}} + <link href="{{static}}/css/api.css" rel="stylesheet" type="text/css"> + {{+partials.title}} + </head> + <body> + {{+partials.header_body title:extensions_title}} + <div id="gc-container"> + {{+partials.extensions_sidenav}} + <div id="gc-pagecontent"> + <h1 class="page_title">chrome.{{api.name}}</h1> + {{?api.permissions.dev}}{{+partials.warning_dev}}{{/}} + {{?api.permissions.beta}}{{+partials.warning_beta}}{{/}} + {{?intro.toc}} + {{+partials.table_of_contents toc_items:intro.toc + has_toc:true + api:api + samples_list:api.samples.extensions + title:extensions_title}} + {{:intro.toc}} + {{+partials.table_of_contents has_toc:false + api:api + samples_list:api.samples.extensions + title:extensions_title}} + {{/intro.toc}} +{{- This is unindented because it contains <pre> tags -}} +{{?intro}} +{{+intro.intro is_apps:false}} +{{/intro}} + {{+partials.api_reference samples_list:api.samples.extensions + title:extensions_title}} + </div> + </div> + </body> + {{+partials.extensions_footer}} +</html> diff --git a/chrome/common/extensions/docs/templates/private/standard_extensions_article.html b/chrome/common/extensions/docs/templates/private/standard_extensions_article.html new file mode 100644 index 0000000..7959f36 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/standard_extensions_article.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> + <head> + {{+partials.header_head}} + <title>{{article.title}} - Google Chrome</title> + </head> + <body> + {{+partials.header_body title:extensions_title}} + <div id="gc-container"> + {{+partials.extensions_sidenav}} + <div id="gc-pagecontent"> + <h1 class="page_title">{{article.title}}</h1> + {{?article.toc}} + {{+partials.table_of_contents toc_items:article.toc + has_toc:true + title:extensions_title}} + {{/article.toc}} +{{- This may contain <pre> tags so it is not indented -}} +{{+article.intro is_apps:false}} + </div> + </div> + </body> + {{+partials.extensions_footer}} +</html> diff --git a/chrome/common/extensions/docs/templates/private/table_of_contents.html b/chrome/common/extensions/docs/templates/private/table_of_contents.html new file mode 100644 index 0000000..576717bd --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/table_of_contents.html @@ -0,0 +1,31 @@ +<div id="toc"> + <h2>Contents</h2> + <ol> + {{?has_toc}} + {{#toc_items}} + <li> + <a href=#{{link}}>{{{title}}}</a> + {{?subheadings}} + <ol> + {{#subheadings}}<li><a href=#{{link}}>{{{title}}}</a></li>{{/}} + </ol> + {{/}} + </li> + {{/toc_items}} + {{/has_toc}} + {{?api}} + <li> + <a href="#apiReference">API reference: chrome.{{api.name}}</a> + <ol> + {{#api}} + {{?api.types}}<li>{{+partials.toc_types}}</li>{{/}} + {{?api.properties}}<li>{{+partials.toc_properties}}</li>{{/}} + {{?api.functions}}<li>{{+partials.toc_functions}}</li>{{/}} + {{?api.events}}<li>{{+partials.toc_events}}</li>{{/}} + {{?samples_list}}<li>{{+partials.toc_samples title:title}}</li>{{/}} + {{/api}} + </ol> + </li> + {{/api}} + </ol> +</div> diff --git a/chrome/common/extensions/docs/templates/private/title.html b/chrome/common/extensions/docs/templates/private/title.html new file mode 100644 index 0000000..8378aea --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/title.html @@ -0,0 +1 @@ +<title>chrome.{{api.name}} - Google Chrome</title> diff --git a/chrome/common/extensions/docs/templates/private/toc_events.html b/chrome/common/extensions/docs/templates/private/toc_events.html new file mode 100644 index 0000000..d1b94ab --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/toc_events.html @@ -0,0 +1,6 @@ +<a href="#{{?prefix}}{{prefix}}-{{/}}events">Events</a> +<ol> + {{#@}} + <li><a href="#event-{{?prefix}}{{prefix}}-{{/}}{{name}}">{{name}}</a></li> + {{/}} +</ol> diff --git a/chrome/common/extensions/docs/templates/private/toc_functions.html b/chrome/common/extensions/docs/templates/private/toc_functions.html new file mode 100644 index 0000000..a94739b --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/toc_functions.html @@ -0,0 +1,6 @@ +<a href="#{{?prefix}}{{prefix}}-{{/}}methods">Methods</a> +<ol> + {{#@}} + <li><a href="#method-{{?prefix}}{{prefix}}-{{/}}{{name}}">{{name}}</a></li> + {{/}} +</ol> diff --git a/chrome/common/extensions/docs/templates/private/toc_properties.html b/chrome/common/extensions/docs/templates/private/toc_properties.html new file mode 100644 index 0000000..eec6754 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/toc_properties.html @@ -0,0 +1,8 @@ +<a href="#{{?prefix}}{{prefix}}-{{/}}properties">Properties</a> +<ol> + {{#@}} + <li><a href="#property-{{?prefix}}{{prefix}}-{{/}}{{name}}">{{name}}</a></li> + {{?functions}}<ol><li>{{+partials.toc_functions prefix:name}}</li></ol>{{/}} + {{?events}}<ol><li>{{+partials.toc_events prefix:name}}</li></ol>{{/}} + {{/}} +</ol> diff --git a/chrome/common/extensions/docs/templates/private/toc_samples.html b/chrome/common/extensions/docs/templates/private/toc_samples.html new file mode 100644 index 0000000..2a26449e --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/toc_samples.html @@ -0,0 +1 @@ +<a href="#samples">Sample {{title}}</a> diff --git a/chrome/common/extensions/docs/templates/private/toc_types.html b/chrome/common/extensions/docs/templates/private/toc_types.html new file mode 100644 index 0000000..5b7f89b --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/toc_types.html @@ -0,0 +1,10 @@ +<a href="#{{?prefix}}{{prefix}}-{{/}}types">Types</a> +<ol> + {{#@}} + <li> + <a href="#type-{{?prefix}}{{prefix}}-{{/}}{{name}}">{{name}}</a> + {{?functions}}<ol><li>{{+partials.toc_functions prefix:name}}</li></ol>{{/}} + {{?events}}<ol><li>{{+partials.toc_events prefix:name}}</li></ol>{{/}} + </li> + {{/}} +</ol> diff --git a/chrome/common/extensions/docs/templates/private/type.html b/chrome/common/extensions/docs/templates/private/type.html new file mode 100644 index 0000000..3ed1467 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/type.html @@ -0,0 +1,23 @@ +<div> + <a name="type-{{name}}"></a> + <h4>{{name}}</h4> + <div> + <dt>{{+partials.type_name}}</dt> + {{?description}}<dd> + {{{description}}} + </dd>{{/description}} + {{?properties}} + <dd><dl>{{#properties}}{{^additional_properties}}{{+partials.property}}{{/}}{{/}}</dl></dd> + {{/properties}} + {{?functions}} + <a name={{type.name}}-methods></a> + <dd><h3>Methods of {{type.name}}</h3> + <dd><dl>{{#functions}}{{+partials.function api:api prefix:type.name}}{{/}}</dl></dd> + {{/functions}} + {{?events}} + <a name={{type.name}}-events></a> + <dd><h3>Events of {{type.name}}</h3> + <dd><dl>{{#events}}{{+partials.event api:api prefix:type.name}}{{/}}</dl></dd> + {{/events}} + </div> +</div> diff --git a/chrome/common/extensions/docs/templates/private/type_name.html b/chrome/common/extensions/docs/templates/private/type_name.html new file mode 100644 index 0000000..54d3001 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/type_name.html @@ -0,0 +1,6 @@ +<span class="type_name"> + ( + {{?optional}}<span class="optional">optional</span>{{/}} + <span id="typeTemplate">{{+partials.variable_type}}</span> + ) +</span> diff --git a/chrome/common/extensions/docs/templates/private/variable_type.html b/chrome/common/extensions/docs/templates/private/variable_type.html new file mode 100644 index 0000000..5fae2a9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/variable_type.html @@ -0,0 +1,20 @@ +{{?link}} +{{+partials.ref_link}} +{{/}} +{{?choices}} +{{#choices}} +{{+partials.variable_type}}{{^@.last}} or {{/}} +{{/}} +{{/}} +{{?array}} +array of {{+partials.variable_type}} +{{/}} +{{?simple_type}} +{{simple_type}} +{{/}} +{{?enum_values}} +enumerated string [{{#enum_values}}"{{name}}"{{^last}}, {{/}}{{/}}] +{{/}} +{{?value}} +<code>{{value}}</code> +{{/}} diff --git a/chrome/common/extensions/docs/templates/private/warning_beta.html b/chrome/common/extensions/docs/templates/private/warning_beta.html new file mode 100644 index 0000000..d4c5edf --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/warning_beta.html @@ -0,0 +1,10 @@ +<p class="warning"> + <em>Warning:</em> This API is still under development. It is only + available for Chrome users on the + <span> + <strong>dev</strong> + <a href="http://www.chromium.org/getting-involved/beta-channel">early + release channel</a> and <strong>beta</strong> + <a href="https://www.google.com/landing/chrome/beta/"> release channel. + </span> +</p> diff --git a/chrome/common/extensions/docs/templates/private/warning_dev.html b/chrome/common/extensions/docs/templates/private/warning_dev.html new file mode 100644 index 0000000..fa9b2e4 --- /dev/null +++ b/chrome/common/extensions/docs/templates/private/warning_dev.html @@ -0,0 +1,8 @@ +<p class="warning"> + <em>Warning:</em> This API is still under development. It is only + available for Chrome users on the + <span> + <strong>dev</strong> + <a href="http://www.chromium.org/getting-involved/dev-channel">early + release channel</a>.</span> +</p> diff --git a/chrome/common/extensions/docs/templates/public/404.html b/chrome/common/extensions/docs/templates/public/404.html new file mode 100644 index 0000000..6bd1569 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/404.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> + <head> + {{+partials.header_head}} + <link href="{{static}}/css/index.css" rel="stylesheet" type="text/css"> + <title>404 Not Found - Google Chrome Extensions</title> + </head> + <body> + {{+partials.header_body title:extensions_title}} + <div id="gc-container"> + <div id="gc-pagecontent"> + <h1 class="page_title">404 - Not Found</h1> + <p>No API or URL found with that name.</p> + </div> + </div> + </body> + {{+partials.footer}} +</html> diff --git a/chrome/common/extensions/docs/templates/public/apps/a11y.html b/chrome/common/extensions/docs/templates/public/apps/a11y.html new file mode 100644 index 0000000..5014292 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/a11y.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.a11y}} diff --git a/chrome/common/extensions/docs/templates/public/apps/about_apps.html b/chrome/common/extensions/docs/templates/public/apps/about_apps.html new file mode 100644 index 0000000..134924c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/about_apps.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.about_apps}} diff --git a/chrome/common/extensions/docs/templates/public/apps/alarms.html b/chrome/common/extensions/docs/templates/public/apps/alarms.html new file mode 100644 index 0000000..d37eda395 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/alarms.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.alarms}} diff --git a/chrome/common/extensions/docs/templates/public/apps/api_index.html b/chrome/common/extensions/docs/templates/public/apps/api_index.html new file mode 100644 index 0000000..4d7b209 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/api_index.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.api_index is_apps:true}} diff --git a/chrome/common/extensions/docs/templates/public/apps/api_other.html b/chrome/common/extensions/docs/templates/public/apps/api_other.html new file mode 100644 index 0000000..b665d61 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/api_other.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.api_other}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_architecture.html b/chrome/common/extensions/docs/templates/public/apps/app_architecture.html new file mode 100644 index 0000000..0e30758 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_architecture.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_architecture}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_csp.html b/chrome/common/extensions/docs/templates/public/apps/app_csp.html new file mode 100644 index 0000000..d9e4ab0 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_csp.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_csp}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_deprecated.html b/chrome/common/extensions/docs/templates/public/apps/app_deprecated.html new file mode 100644 index 0000000..c9fa3b6 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_deprecated.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_deprecated}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_external.html b/chrome/common/extensions/docs/templates/public/apps/app_external.html new file mode 100644 index 0000000..d493284 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_external.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_external}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_frameworks.html b/chrome/common/extensions/docs/templates/public/apps/app_frameworks.html new file mode 100644 index 0000000..af5c77d2 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_frameworks.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_frameworks}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_hardware.html b/chrome/common/extensions/docs/templates/public/apps/app_hardware.html new file mode 100644 index 0000000..98db693 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_hardware.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_hardware}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_identity.html b/chrome/common/extensions/docs/templates/public/apps/app_identity.html new file mode 100644 index 0000000..ce60fa5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_identity.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_identity}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_intents.html b/chrome/common/extensions/docs/templates/public/apps/app_intents.html new file mode 100644 index 0000000..e2d4c67 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_intents.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_intents}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_known_issues.html b/chrome/common/extensions/docs/templates/public/apps/app_known_issues.html new file mode 100644 index 0000000..7083c1b --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_known_issues.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_known_issues}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_lifecycle.html b/chrome/common/extensions/docs/templates/public/apps/app_lifecycle.html new file mode 100644 index 0000000..6b39b869 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_lifecycle.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_lifecycle}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_network.html b/chrome/common/extensions/docs/templates/public/apps/app_network.html new file mode 100644 index 0000000..72d47bb --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_network.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_network}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_runtime.html b/chrome/common/extensions/docs/templates/public/apps/app_runtime.html new file mode 100644 index 0000000..c3bb6ca --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_runtime.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.app_runtime}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_storage.html b/chrome/common/extensions/docs/templates/public/apps/app_storage.html new file mode 100644 index 0000000..ecc8a1f --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_storage.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.app_storage}} diff --git a/chrome/common/extensions/docs/templates/public/apps/app_window.html b/chrome/common/extensions/docs/templates/public/apps/app_window.html new file mode 100644 index 0000000..2bb1aa5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/app_window.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.app_window}} diff --git a/chrome/common/extensions/docs/templates/public/apps/autoupdate.html b/chrome/common/extensions/docs/templates/public/apps/autoupdate.html new file mode 100644 index 0000000..84551bc --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/autoupdate.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.autoupdate}} diff --git a/chrome/common/extensions/docs/templates/public/apps/background_pages.html b/chrome/common/extensions/docs/templates/public/apps/background_pages.html new file mode 100644 index 0000000..f2d6f84 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/background_pages.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.background_pages}} diff --git a/chrome/common/extensions/docs/templates/public/apps/contentSecurityPolicy.html b/chrome/common/extensions/docs/templates/public/apps/contentSecurityPolicy.html new file mode 100644 index 0000000..b4c86ea --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/contentSecurityPolicy.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.contentSecurityPolicy}} diff --git a/chrome/common/extensions/docs/templates/public/apps/content_scripts.html b/chrome/common/extensions/docs/templates/public/apps/content_scripts.html new file mode 100644 index 0000000..80f1fbc --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/content_scripts.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.content_scripts}} diff --git a/chrome/common/extensions/docs/templates/public/apps/contextMenus.html b/chrome/common/extensions/docs/templates/public/apps/contextMenus.html new file mode 100644 index 0000000..c8e3649 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/contextMenus.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.context_menus intro:intros.contextMenus}} diff --git a/chrome/common/extensions/docs/templates/public/apps/crx.html b/chrome/common/extensions/docs/templates/public/apps/crx.html new file mode 100644 index 0000000..d7c5b69 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/crx.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.crx}} diff --git a/chrome/common/extensions/docs/templates/public/apps/develop_apps.html b/chrome/common/extensions/docs/templates/public/apps/develop_apps.html new file mode 100644 index 0000000..0c86785 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/develop_apps.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.develop_apps}} diff --git a/chrome/common/extensions/docs/templates/public/apps/devguide.html b/chrome/common/extensions/docs/templates/public/apps/devguide.html new file mode 100644 index 0000000..7be8259 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/devguide.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.devguide}} diff --git a/chrome/common/extensions/docs/templates/public/apps/devtools.html b/chrome/common/extensions/docs/templates/public/apps/devtools.html new file mode 100644 index 0000000..06ec7a8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/devtools.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.devtools}} diff --git a/chrome/common/extensions/docs/templates/public/apps/docs.html b/chrome/common/extensions/docs/templates/public/apps/docs.html new file mode 100644 index 0000000..714521d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/docs.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.docs}} diff --git a/chrome/common/extensions/docs/templates/public/apps/event_pages.html b/chrome/common/extensions/docs/templates/public/apps/event_pages.html new file mode 100644 index 0000000..d75de6f --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/event_pages.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.event_pages}} diff --git a/chrome/common/extensions/docs/templates/public/apps/events.html b/chrome/common/extensions/docs/templates/public/apps/events.html new file mode 100644 index 0000000..69899cf --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/events.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.events intro:intros.events}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental.html b/chrome/common/extensions/docs/templates/public/apps/experimental.html new file mode 100644 index 0000000..7341484 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental is_apps:true}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_app.html b/chrome/common/extensions/docs/templates/public/apps/experimental_app.html new file mode 100644 index 0000000..a2efc68 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_app.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.experimental_app intro:intros.experimental_app}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_bluetooth.html b/chrome/common/extensions/docs/templates/public/apps/experimental_bluetooth.html new file mode 100644 index 0000000..5d9215a --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_bluetooth.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.experimental_bluetooth}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_contextMenus.html b/chrome/common/extensions/docs/templates/public/apps/experimental_contextMenus.html new file mode 100644 index 0000000..4a6c637 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_contextMenus.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_contextMenus}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_inspectedWindow.html b/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_inspectedWindow.html new file mode 100644 index 0000000..aac2044 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_inspectedWindow.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_devtools_inspectedWindow}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_network.html b/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_network.html new file mode 100644 index 0000000..67ea061 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_network.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_devtools_network}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_panels.html b/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_panels.html new file mode 100644 index 0000000..4beef46 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_panels.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_devtools_panels}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_resources.html b/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_resources.html new file mode 100644 index 0000000..f9bf1ae --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_devtools_resources.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_devtools_resources}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_identity.html b/chrome/common/extensions/docs/templates/public/apps/experimental_identity.html new file mode 100644 index 0000000..39ee7cb --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_identity.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.experimental_identity}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_inputUI.html b/chrome/common/extensions/docs/templates/public/apps/experimental_inputUI.html new file mode 100644 index 0000000..79a28ce --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_inputUI.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_inputUI}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_mediaGalleries.html b/chrome/common/extensions/docs/templates/public/apps/experimental_mediaGalleries.html new file mode 100644 index 0000000..880079e --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_mediaGalleries.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.experimental_media_galleries}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_record.html b/chrome/common/extensions/docs/templates/public/apps/experimental_record.html new file mode 100644 index 0000000..e1bc956 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_record.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.experimental_record}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_storage.html b/chrome/common/extensions/docs/templates/public/apps/experimental_storage.html new file mode 100644 index 0000000..69dda53 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_storage.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_storage}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_systemInfo_cpu.html b/chrome/common/extensions/docs/templates/public/apps/experimental_systemInfo_cpu.html new file mode 100644 index 0000000..52cffba --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_systemInfo_cpu.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.experimental_system_info_cpu}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_systemInfo_storage.html b/chrome/common/extensions/docs/templates/public/apps/experimental_systemInfo_storage.html new file mode 100644 index 0000000..b17be1e --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_systemInfo_storage.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.experimental_system_info_storage}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_usb.html b/chrome/common/extensions/docs/templates/public/apps/experimental_usb.html new file mode 100644 index 0000000..b8880ab --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_usb.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.experimental_usb}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector.html b/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector.html new file mode 100644 index 0000000..549aeb8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_webInspector}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector_audits.html b/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector_audits.html new file mode 100644 index 0000000..c00981d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector_audits.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_webInspector_audits}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector_panels.html b/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector_panels.html new file mode 100644 index 0000000..6541843 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector_panels.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_webInspector_panels}} diff --git a/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector_resources.html b/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector_resources.html new file mode 100644 index 0000000..96ea172 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/experimental_webInspector_resources.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.experimental_webInspector_resources}} diff --git a/chrome/common/extensions/docs/templates/public/apps/external_extensions.html b/chrome/common/extensions/docs/templates/public/apps/external_extensions.html new file mode 100644 index 0000000..715bc1b --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/external_extensions.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.external_extensions}} diff --git a/chrome/common/extensions/docs/templates/public/apps/faq.html b/chrome/common/extensions/docs/templates/public/apps/faq.html new file mode 100644 index 0000000..84fe405 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/faq.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.faq}} diff --git a/chrome/common/extensions/docs/templates/public/apps/fileSystem.html b/chrome/common/extensions/docs/templates/public/apps/fileSystem.html new file mode 100644 index 0000000..c5062ef --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/fileSystem.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.file_system}} diff --git a/chrome/common/extensions/docs/templates/public/apps/first_app.html b/chrome/common/extensions/docs/templates/public/apps/first_app.html new file mode 100644 index 0000000..664a89b --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/first_app.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.first_app}} diff --git a/chrome/common/extensions/docs/templates/public/apps/getstarted.html b/chrome/common/extensions/docs/templates/public/apps/getstarted.html new file mode 100644 index 0000000..612efb3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/getstarted.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.getstarted}} diff --git a/chrome/common/extensions/docs/templates/public/apps/hosting.html b/chrome/common/extensions/docs/templates/public/apps/hosting.html new file mode 100644 index 0000000..7947899 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/hosting.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.hosting}} diff --git a/chrome/common/extensions/docs/templates/public/apps/i18n-messages.html b/chrome/common/extensions/docs/templates/public/apps/i18n-messages.html new file mode 100644 index 0000000..ff5c891 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/i18n-messages.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.i18n-messages}} diff --git a/chrome/common/extensions/docs/templates/public/apps/i18n.html b/chrome/common/extensions/docs/templates/public/apps/i18n.html new file mode 100644 index 0000000..1b82694 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/i18n.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.i18n intro:intros.i18n}} diff --git a/chrome/common/extensions/docs/templates/public/apps/idle.html b/chrome/common/extensions/docs/templates/public/apps/idle.html new file mode 100644 index 0000000..1ed9950 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/idle.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.idle intro:intros.idle}} diff --git a/chrome/common/extensions/docs/templates/public/apps/index.html b/chrome/common/extensions/docs/templates/public/apps/index.html new file mode 100644 index 0000000..a25d506 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/index.html @@ -0,0 +1 @@ +<html><head><meta http-equiv="refresh" content="0;URL='about_apps.html'"></head></html> diff --git a/chrome/common/extensions/docs/templates/public/apps/manifest.html b/chrome/common/extensions/docs/templates/public/apps/manifest.html new file mode 100644 index 0000000..d073c92 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/manifest.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.manifest}} diff --git a/chrome/common/extensions/docs/templates/public/apps/manifestVersion.html b/chrome/common/extensions/docs/templates/public/apps/manifestVersion.html new file mode 100644 index 0000000..b49d5fa --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/manifestVersion.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.manifestVersion}} diff --git a/chrome/common/extensions/docs/templates/public/apps/match_patterns.html b/chrome/common/extensions/docs/templates/public/apps/match_patterns.html new file mode 100644 index 0000000..f327243 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/match_patterns.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.match_patterns}} diff --git a/chrome/common/extensions/docs/templates/public/apps/mediaGalleries.html b/chrome/common/extensions/docs/templates/public/apps/mediaGalleries.html new file mode 100644 index 0000000..6468eb2 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/mediaGalleries.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.media_galleries intro:intros.mediaGalleries}} diff --git a/chrome/common/extensions/docs/templates/public/apps/messaging.html b/chrome/common/extensions/docs/templates/public/apps/messaging.html new file mode 100644 index 0000000..e4c18e3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/messaging.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.messaging}} diff --git a/chrome/common/extensions/docs/templates/public/apps/notifications.html b/chrome/common/extensions/docs/templates/public/apps/notifications.html new file mode 100644 index 0000000..e2e19af --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/notifications.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.notifications}} diff --git a/chrome/common/extensions/docs/templates/public/apps/npapi.html b/chrome/common/extensions/docs/templates/public/apps/npapi.html new file mode 100644 index 0000000..51eddac --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/npapi.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.npapi}} diff --git a/chrome/common/extensions/docs/templates/public/apps/offline_apps.html b/chrome/common/extensions/docs/templates/public/apps/offline_apps.html new file mode 100644 index 0000000..dafda5c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/offline_apps.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.offline_apps}} diff --git a/chrome/common/extensions/docs/templates/public/apps/options.html b/chrome/common/extensions/docs/templates/public/apps/options.html new file mode 100644 index 0000000..267e080 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/options.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.options}} diff --git a/chrome/common/extensions/docs/templates/public/apps/override.html b/chrome/common/extensions/docs/templates/public/apps/override.html new file mode 100644 index 0000000..6dbb5d6 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/override.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.override}} diff --git a/chrome/common/extensions/docs/templates/public/apps/overview.html b/chrome/common/extensions/docs/templates/public/apps/overview.html new file mode 100644 index 0000000..8504647 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/overview.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.overview}} diff --git a/chrome/common/extensions/docs/templates/public/apps/packaging.html b/chrome/common/extensions/docs/templates/public/apps/packaging.html new file mode 100644 index 0000000..c8d7fac --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/packaging.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.packaging}} diff --git a/chrome/common/extensions/docs/templates/public/apps/permission_warnings.html b/chrome/common/extensions/docs/templates/public/apps/permission_warnings.html new file mode 100644 index 0000000..54248d6 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/permission_warnings.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.permission_warnings}} diff --git a/chrome/common/extensions/docs/templates/public/apps/permissions.html b/chrome/common/extensions/docs/templates/public/apps/permissions.html new file mode 100644 index 0000000..85a114f --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/permissions.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.permissions intro:intros.permissions}} diff --git a/chrome/common/extensions/docs/templates/public/apps/publish_app.html b/chrome/common/extensions/docs/templates/public/apps/publish_app.html new file mode 100644 index 0000000..d3b94c24 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/publish_app.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.publish_app}} diff --git a/chrome/common/extensions/docs/templates/public/apps/runtime.html b/chrome/common/extensions/docs/templates/public/apps/runtime.html new file mode 100644 index 0000000..f7d5626 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/runtime.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.runtime}} diff --git a/chrome/common/extensions/docs/templates/public/apps/samples.html b/chrome/common/extensions/docs/templates/public/apps/samples.html new file mode 100644 index 0000000..c91d0c3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/samples.html @@ -0,0 +1,5 @@ +{{+partials.samples sidenav:partials.apps_sidenav + filter_list:api_list.apps.chrome + samples_list:samples.apps + footer:partials.apps_footer + title:apps_title}} diff --git a/chrome/common/extensions/docs/templates/public/apps/sandboxingEval.html b/chrome/common/extensions/docs/templates/public/apps/sandboxingEval.html new file mode 100644 index 0000000..3e0c1e3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/sandboxingEval.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.sandboxingEval}} diff --git a/chrome/common/extensions/docs/templates/public/apps/serial.html b/chrome/common/extensions/docs/templates/public/apps/serial.html new file mode 100644 index 0000000..de040bf --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/serial.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.serial}} diff --git a/chrome/common/extensions/docs/templates/public/apps/socket.html b/chrome/common/extensions/docs/templates/public/apps/socket.html new file mode 100644 index 0000000..d9e4809 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/socket.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.socket intro:intros.socket}}
\ No newline at end of file diff --git a/chrome/common/extensions/docs/templates/public/apps/storage.html b/chrome/common/extensions/docs/templates/public/apps/storage.html new file mode 100644 index 0000000..90c3fc2 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/storage.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.storage intro:intros.storage}} diff --git a/chrome/common/extensions/docs/templates/public/apps/themes.html b/chrome/common/extensions/docs/templates/public/apps/themes.html new file mode 100644 index 0000000..ee72c5d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/themes.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.themes}} diff --git a/chrome/common/extensions/docs/templates/public/apps/tts.html b/chrome/common/extensions/docs/templates/public/apps/tts.html new file mode 100644 index 0000000..6913c00 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/tts.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.tts intro:intros.tts}} diff --git a/chrome/common/extensions/docs/templates/public/apps/tut_analytics.html b/chrome/common/extensions/docs/templates/public/apps/tut_analytics.html new file mode 100644 index 0000000..6e3a4fc --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/tut_analytics.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.tut_analytics}} diff --git a/chrome/common/extensions/docs/templates/public/apps/tut_debugging.html b/chrome/common/extensions/docs/templates/public/apps/tut_debugging.html new file mode 100644 index 0000000..d9051b0 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/tut_debugging.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.tut_debugging}} diff --git a/chrome/common/extensions/docs/templates/public/apps/tut_oauth.html b/chrome/common/extensions/docs/templates/public/apps/tut_oauth.html new file mode 100644 index 0000000..8a360bf --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/tut_oauth.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.tut_oauth}} diff --git a/chrome/common/extensions/docs/templates/public/apps/tutorials.html b/chrome/common/extensions/docs/templates/public/apps/tutorials.html new file mode 100644 index 0000000..8f2389b --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/tutorials.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.tutorials}} diff --git a/chrome/common/extensions/docs/templates/public/apps/types.html b/chrome/common/extensions/docs/templates/public/apps/types.html new file mode 100644 index 0000000..3023505 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/types.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.types intro:intros.types}} diff --git a/chrome/common/extensions/docs/templates/public/apps/webstore.html b/chrome/common/extensions/docs/templates/public/apps/webstore.html new file mode 100644 index 0000000..f7cfb28 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/webstore.html @@ -0,0 +1 @@ +{{+partials.standard_apps_api api:apis.webstore}} diff --git a/chrome/common/extensions/docs/templates/public/apps/whats_new.html b/chrome/common/extensions/docs/templates/public/apps/whats_new.html new file mode 100644 index 0000000..65959e8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/whats_new.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.whats_new}} diff --git a/chrome/common/extensions/docs/templates/public/apps/xhr.html b/chrome/common/extensions/docs/templates/public/apps/xhr.html new file mode 100644 index 0000000..34be1c2 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/apps/xhr.html @@ -0,0 +1 @@ +{{+partials.standard_apps_article article:intros.xhr}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/a11y.html b/chrome/common/extensions/docs/templates/public/extensions/a11y.html new file mode 100644 index 0000000..ffa8b22 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/a11y.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.a11y}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/alarms.html b/chrome/common/extensions/docs/templates/public/extensions/alarms.html new file mode 100644 index 0000000..855b4b9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/alarms.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.alarms}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/api_index.html b/chrome/common/extensions/docs/templates/public/extensions/api_index.html new file mode 100644 index 0000000..794c225 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/api_index.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.api_index is_apps:false}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/api_other.html b/chrome/common/extensions/docs/templates/public/extensions/api_other.html new file mode 100644 index 0000000..3072c0b --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/api_other.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.api_other}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/apps.html b/chrome/common/extensions/docs/templates/public/extensions/apps.html new file mode 100644 index 0000000..898f3fc --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/apps.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.apps}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/autoupdate.html b/chrome/common/extensions/docs/templates/public/extensions/autoupdate.html new file mode 100644 index 0000000..7ad2b5d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/autoupdate.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.autoupdate}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/background_pages.html b/chrome/common/extensions/docs/templates/public/extensions/background_pages.html new file mode 100644 index 0000000..4f70c7d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/background_pages.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.background_pages}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/bookmarks.html b/chrome/common/extensions/docs/templates/public/extensions/bookmarks.html new file mode 100644 index 0000000..d2a36f6 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/bookmarks.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.bookmarks intro:intros.bookmarks}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/browserAction.html b/chrome/common/extensions/docs/templates/public/extensions/browserAction.html new file mode 100644 index 0000000..ae1b726 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/browserAction.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.browser_action intro:intros.browserAction}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/browsingData.html b/chrome/common/extensions/docs/templates/public/extensions/browsingData.html new file mode 100644 index 0000000..18db5c8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/browsingData.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.browsing_data intro:intros.browsingData}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/commands.html b/chrome/common/extensions/docs/templates/public/extensions/commands.html new file mode 100644 index 0000000..99189c9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/commands.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.commands intro:intros.commands}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/contentSecurityPolicy.html b/chrome/common/extensions/docs/templates/public/extensions/contentSecurityPolicy.html new file mode 100644 index 0000000..46abbdc --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/contentSecurityPolicy.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.contentSecurityPolicy}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/contentSettings.html b/chrome/common/extensions/docs/templates/public/extensions/contentSettings.html new file mode 100644 index 0000000..5aac9c9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/contentSettings.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.content_settings intro:intros.contentSettings}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/content_scripts.html b/chrome/common/extensions/docs/templates/public/extensions/content_scripts.html new file mode 100644 index 0000000..dfb657f5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/content_scripts.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.content_scripts}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/contextMenus.html b/chrome/common/extensions/docs/templates/public/extensions/contextMenus.html new file mode 100644 index 0000000..075a30e --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/contextMenus.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.context_menus intro:intros.contextMenus}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/cookies.html b/chrome/common/extensions/docs/templates/public/extensions/cookies.html new file mode 100644 index 0000000..c1d4a42 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/cookies.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.cookies intro:intros.cookies}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/crx.html b/chrome/common/extensions/docs/templates/public/extensions/crx.html new file mode 100644 index 0000000..ad07520 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/crx.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.crx}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/debugger.html b/chrome/common/extensions/docs/templates/public/extensions/debugger.html new file mode 100644 index 0000000..d3d4a09 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/debugger.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.debugger intro:intros.debugger}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/declarativeWebRequest.html b/chrome/common/extensions/docs/templates/public/extensions/declarativeWebRequest.html new file mode 100644 index 0000000..839bd55 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/declarativeWebRequest.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.declarative_web_request intro:intros.declarativeWebRequest}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/devguide.html b/chrome/common/extensions/docs/templates/public/extensions/devguide.html new file mode 100644 index 0000000..fc0357e --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/devguide.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.devguide}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/devtools.html b/chrome/common/extensions/docs/templates/public/extensions/devtools.html new file mode 100644 index 0000000..7d763cb --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/devtools.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.devtools}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/devtools_inspectedWindow.html b/chrome/common/extensions/docs/templates/public/extensions/devtools_inspectedWindow.html new file mode 100644 index 0000000..459e573 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/devtools_inspectedWindow.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.devtools/inspected_window intro:intros.devtools_inspectedWindow}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/devtools_network.html b/chrome/common/extensions/docs/templates/public/extensions/devtools_network.html new file mode 100644 index 0000000..985744d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/devtools_network.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.devtools/network intro:intros.devtools_network}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/devtools_panels.html b/chrome/common/extensions/docs/templates/public/extensions/devtools_panels.html new file mode 100644 index 0000000..0d7fae8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/devtools_panels.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.devtools/panels intro:intros.devtools_panels}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/docs.html b/chrome/common/extensions/docs/templates/public/extensions/docs.html new file mode 100644 index 0000000..f2089ae --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/docs.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.docs}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/downloads.html b/chrome/common/extensions/docs/templates/public/extensions/downloads.html new file mode 100644 index 0000000..909d110 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/downloads.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.downloads intro:intros.downloads}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/event_pages.html b/chrome/common/extensions/docs/templates/public/extensions/event_pages.html new file mode 100644 index 0000000..e205377 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/event_pages.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.event_pages}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/events.html b/chrome/common/extensions/docs/templates/public/extensions/events.html new file mode 100644 index 0000000..d1eb774 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/events.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.events intro:intros.events}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental.html b/chrome/common/extensions/docs/templates/public/extensions/experimental.html new file mode 100644 index 0000000..aebc122 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental is_apps:false}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_bluetooth.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_bluetooth.html new file mode 100644 index 0000000..793b430 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_bluetooth.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_bluetooth}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_browsingData.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_browsingData.html new file mode 100644 index 0000000..db17845 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_browsingData.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_browsingData}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_contentSettings.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_contentSettings.html new file mode 100644 index 0000000..dfd3f8e --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_contentSettings.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_contentSettings}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_contextMenus.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_contextMenus.html new file mode 100644 index 0000000..697a8ad --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_contextMenus.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_contextMenus}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_cookies.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_cookies.html new file mode 100644 index 0000000..baad5da --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_cookies.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_cookies}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_debugger.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_debugger.html new file mode 100644 index 0000000..782fe2f --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_debugger.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_debugger}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools.html new file mode 100644 index 0000000..6d2581a --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_devtools}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_audits.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_audits.html new file mode 100644 index 0000000..eca386d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_audits.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.devtools/experimental_audits intro:intros.experimental_devtools_audits}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_console.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_console.html new file mode 100644 index 0000000..5e9e474 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_console.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.devtools/experimental_console intro:intros.experimental_devtools_console}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_inspectedWindow.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_inspectedWindow.html new file mode 100644 index 0000000..a69609cd --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_inspectedWindow.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_devtools_inspectedWindow}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_network.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_network.html new file mode 100644 index 0000000..2812d5c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_network.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_devtools_network}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_panels.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_panels.html new file mode 100644 index 0000000..a083919 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_panels.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_devtools_panels}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_resources.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_resources.html new file mode 100644 index 0000000..1e134a3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_devtools_resources.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_devtools_resources}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_discovery.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_discovery.html new file mode 100644 index 0000000..74e16f2 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_discovery.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_discovery intro:intros.experimental_discovery}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_history.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_history.html new file mode 100644 index 0000000..5e6b703 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_history.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_history}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_identity.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_identity.html new file mode 100644 index 0000000..9c9b563 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_identity.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_identity}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_infobars.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_infobars.html new file mode 100644 index 0000000..194ecf3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_infobars.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_infobars intro:intros.experimental_infobars}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_inputUI.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_inputUI.html new file mode 100644 index 0000000..b530c88 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_inputUI.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_inputUI}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_offscreenTabs.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_offscreenTabs.html new file mode 100644 index 0000000..f3540d7 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_offscreenTabs.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_offscreen_tabs}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_privacy.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_privacy.html new file mode 100644 index 0000000..9b878ba --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_privacy.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_privacy}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_processes.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_processes.html new file mode 100644 index 0000000..ee75b84 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_processes.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_processes}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_record.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_record.html new file mode 100644 index 0000000..0dde07f --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_record.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_record}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_speechInput.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_speechInput.html new file mode 100644 index 0000000..ac10ceb --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_speechInput.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_speech_input intro:intros.experimental_speechInput}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_storage.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_storage.html new file mode 100644 index 0000000..d98bcee --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_storage.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_storage}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_systemInfo_cpu.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_systemInfo_cpu.html new file mode 100644 index 0000000..58ff877 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_systemInfo_cpu.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_system_info_cpu}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_systemInfo_storage.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_systemInfo_storage.html new file mode 100644 index 0000000..c87446c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_systemInfo_storage.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_system_info_storage}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_usb.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_usb.html new file mode 100644 index 0000000..dd090328 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_usb.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.experimental_usb}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector.html new file mode 100644 index 0000000..46e98c1 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_webInspector}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector_audits.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector_audits.html new file mode 100644 index 0000000..4539a01 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector_audits.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_webInspector_audits}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector_panels.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector_panels.html new file mode 100644 index 0000000..9841ada --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector_panels.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_webInspector_panels}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector_resources.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector_resources.html new file mode 100644 index 0000000..45fe1a6 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_webInspector_resources.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_webInspector_resources}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/experimental_webRequest.html b/chrome/common/extensions/docs/templates/public/extensions/experimental_webRequest.html new file mode 100644 index 0000000..083f3e5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/experimental_webRequest.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.experimental_webRequest}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/extension.html b/chrome/common/extensions/docs/templates/public/extensions/extension.html new file mode 100644 index 0000000..728ad75 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/extension.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.extension intro:intros.extension}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/external_extensions.html b/chrome/common/extensions/docs/templates/public/extensions/external_extensions.html new file mode 100644 index 0000000..6503ca1 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/external_extensions.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.external_extensions}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/faq.html b/chrome/common/extensions/docs/templates/public/extensions/faq.html new file mode 100644 index 0000000..ae611ce --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/faq.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.faq}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/fileBrowserHandler.html b/chrome/common/extensions/docs/templates/public/extensions/fileBrowserHandler.html new file mode 100644 index 0000000..de0a261 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/fileBrowserHandler.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.file_browser_handler intro:intros.fileBrowserHandler}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/fontSettings.html b/chrome/common/extensions/docs/templates/public/extensions/fontSettings.html new file mode 100644 index 0000000..a09fcd9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/fontSettings.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.font_settings intro:intros.fontSettings}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/getstarted.html b/chrome/common/extensions/docs/templates/public/extensions/getstarted.html new file mode 100644 index 0000000..2e4c001 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/getstarted.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.getstarted}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/history.html b/chrome/common/extensions/docs/templates/public/extensions/history.html new file mode 100644 index 0000000..33d199c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/history.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.history intro:intros.history}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/hosting.html b/chrome/common/extensions/docs/templates/public/extensions/hosting.html new file mode 100644 index 0000000..3f3730c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/hosting.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.hosting}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/i18n-messages.html b/chrome/common/extensions/docs/templates/public/extensions/i18n-messages.html new file mode 100644 index 0000000..9a698e3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/i18n-messages.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.i18n-messages}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/i18n.html b/chrome/common/extensions/docs/templates/public/extensions/i18n.html new file mode 100644 index 0000000..3fac07c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/i18n.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.i18n intro:intros.i18n}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/idle.html b/chrome/common/extensions/docs/templates/public/extensions/idle.html new file mode 100644 index 0000000..19a7e96 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/idle.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.idle intro:intros.idle}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/index.html b/chrome/common/extensions/docs/templates/public/extensions/index.html new file mode 100644 index 0000000..f7a0f84 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/index.html @@ -0,0 +1,100 @@ +<!DOCTYPE html> +<html> + <head> + {{+partials.header_head}} + <link href="{{static}}/css/index.css" rel="stylesheet" type="text/css"> + <title>Google Chrome Extensions</title> + </head> + <body> + {{+partials.header_body title:extensions_title}} + <div id="gc-container"> + <div id="gc-pagecontent"> + <table id="index"> + <tr> + <td> + <h3>What are extensions?</h3> + <p> + Extensions are small software programs that + can modify and enhance the functionality of the Chrome browser. + You write them using web technologies such as + HTML, JavaScript, and CSS. + You can also use the extension system to build + <a href="apps.html">packaged apps</a>, + a downloadable kind of + <a href="http://code.google.com/chrome/apps/index.html">installable web app</a>. + </p> + <p> + <img src="{{static}}/images/index/gmail-small.png" width="91" height="35" align="right" style="margin-top:0px; margin-left:0.5em" alt="A screenshot of an extension's icon in the browser bar"> + From a user's point of view, + extensions and packaged apps are very different + because they present very different user interfaces. + Extensions have little to no user interface. + For example, the image to the right shows the icon + that provides the UI for the + <a href="samples.html#gmail">Gmail extension</a>. + </p> + <p> + <img src="{{static}}/images/index/html5app.png" width="200" height="160" align="right" style="margin-top:0px; margin-left:0.5em" alt="A screenshot of a packaged app that implements a jigsaw puzzle"> + Packaged apps, on the other hand, + look and feel like regular web apps, + with a big-screen design + and rich UI. + The image to the right shows a jigsaw puzzle game + implemented by a packaged app. + </p> + <p> + Both extensions and packaged apps bundle all their files + into a single file that the user downloads and installs. + This bundling means that, unlike ordinary web apps, + extensions and packaged apps don't need to depend + on content from the web. + </p> + <p> + You can distribute your extension or packaged app + by using the + <a href="https://chrome.google.com/webstore/developer/dashboard">Chrome Developer Dashboard</a> + to publish to the + <a href="http://chrome.google.com/webstore">Chrome Web Store</a>. + For more information, see the + <a href="http://code.google.com/chrome/webstore">store developer documentation</a>. + </p> + </td> + <td id="howDoIStart"> + <h3>How do I start?</h3> + <p></p> + <ol> + <li> + Follow the <a href="getstarted.html">Getting Started tutorial</a> + <!-- PENDING: once we have one for packaged apps, change to + "for _extensions_ or _packaged_apps_" --> + </li> + <li> + Read the + <a href="overview.html">Overview</a> + </li> + <li> + Keep up-to-date by reading the + <a href="http://blog.chromium.org/">Chromium blog</a> + </li> + <li> + Subscribe to the + <a href="http://groups.google.com/a/chromium.org/group/chromium-extensions">chromium-extensions group</a> + </li> + </ol> + <p></p> + <h3>Featured videos</h3> + <p> + <a href="http://www.youtube.com/view_play_list?p=CA101D6A85FE9D4B">Technical videos</a> <br> + <a href="http://www.youtube.com/view_play_list?p=38DF05697DE372B1">Developer snapshots</a> (below) + </p> + <p> + <iframe title="YouTube video player" width="300" height="199" src="http://www.youtube.com/embed/wRDPTnY3yO8?rel=0" frameborder="0" allowfullscreen=""></iframe> + </p> + </td> + </tr> + </table> + </div> + </div> + </body> + {{+partials.extensions_footer}} +</html> diff --git a/chrome/common/extensions/docs/templates/public/extensions/input_ime.html b/chrome/common/extensions/docs/templates/public/extensions/input_ime.html new file mode 100644 index 0000000..9390540 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/input_ime.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.input_ime}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/management.html b/chrome/common/extensions/docs/templates/public/extensions/management.html new file mode 100644 index 0000000..8d9b334 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/management.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.management intro:intros.management}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/manifest.html b/chrome/common/extensions/docs/templates/public/extensions/manifest.html new file mode 100644 index 0000000..7f40b8d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/manifest.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.manifest}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/manifestVersion.html b/chrome/common/extensions/docs/templates/public/extensions/manifestVersion.html new file mode 100644 index 0000000..61f21a5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/manifestVersion.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.manifestVersion}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/match_patterns.html b/chrome/common/extensions/docs/templates/public/extensions/match_patterns.html new file mode 100644 index 0000000..6fb437c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/match_patterns.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.match_patterns}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/messaging.html b/chrome/common/extensions/docs/templates/public/extensions/messaging.html new file mode 100644 index 0000000..bd9d8bf --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/messaging.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.messaging}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/notifications.html b/chrome/common/extensions/docs/templates/public/extensions/notifications.html new file mode 100644 index 0000000..72a57bc --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/notifications.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.notifications}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/npapi.html b/chrome/common/extensions/docs/templates/public/extensions/npapi.html new file mode 100644 index 0000000..81dd45a --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/npapi.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.npapi}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/omnibox.html b/chrome/common/extensions/docs/templates/public/extensions/omnibox.html new file mode 100644 index 0000000..565382b --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/omnibox.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.omnibox intro:intros.omnibox}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/options.html b/chrome/common/extensions/docs/templates/public/extensions/options.html new file mode 100644 index 0000000..3825d01 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/options.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.options}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/override.html b/chrome/common/extensions/docs/templates/public/extensions/override.html new file mode 100644 index 0000000..bcc91238 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/override.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.override}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/overview.html b/chrome/common/extensions/docs/templates/public/extensions/overview.html new file mode 100644 index 0000000..b1511c8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/overview.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.overview}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/packaging.html b/chrome/common/extensions/docs/templates/public/extensions/packaging.html new file mode 100644 index 0000000..8483d40 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/packaging.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.packaging}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/pageAction.html b/chrome/common/extensions/docs/templates/public/extensions/pageAction.html new file mode 100644 index 0000000..2889fcb --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/pageAction.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.page_action intro:intros.pageAction}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/pageCapture.html b/chrome/common/extensions/docs/templates/public/extensions/pageCapture.html new file mode 100644 index 0000000..7a43702 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/pageCapture.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.page_capture intro:intros.pageCapture}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/permission_warnings.html b/chrome/common/extensions/docs/templates/public/extensions/permission_warnings.html new file mode 100644 index 0000000..d89cc33 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/permission_warnings.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.permission_warnings}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/permissions.html b/chrome/common/extensions/docs/templates/public/extensions/permissions.html new file mode 100644 index 0000000..83b21d3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/permissions.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.permissions intro:intros.permissions}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/privacy.html b/chrome/common/extensions/docs/templates/public/extensions/privacy.html new file mode 100644 index 0000000..08152f9 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/privacy.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.privacy intro:intros.privacy}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/proxy.html b/chrome/common/extensions/docs/templates/public/extensions/proxy.html new file mode 100644 index 0000000..8c240e8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/proxy.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.proxy intro:intros.proxy}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/runtime.html b/chrome/common/extensions/docs/templates/public/extensions/runtime.html new file mode 100644 index 0000000..298cc9c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/runtime.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.runtime}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/samples.html b/chrome/common/extensions/docs/templates/public/extensions/samples.html new file mode 100644 index 0000000..feb5e71 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/samples.html @@ -0,0 +1,5 @@ +{{+partials.samples sidenav:partials.extensions_sidenav + filter_list:api_list.extensions.chrome + samples_list:samples.extensions + footer:partials.extensions_footer + title:extensions_title}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/sandboxingEval.html b/chrome/common/extensions/docs/templates/public/extensions/sandboxingEval.html new file mode 100644 index 0000000..019a38d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/sandboxingEval.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.sandboxingEval}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/scriptBadge.html b/chrome/common/extensions/docs/templates/public/extensions/scriptBadge.html new file mode 100644 index 0000000..43a090a --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/scriptBadge.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.script_badge}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/storage.html b/chrome/common/extensions/docs/templates/public/extensions/storage.html new file mode 100644 index 0000000..b0b0834 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/storage.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.storage intro:intros.storage}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/tabs.html b/chrome/common/extensions/docs/templates/public/extensions/tabs.html new file mode 100644 index 0000000..04938b8 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/tabs.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.tabs intro:intros.tabs}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/themes.html b/chrome/common/extensions/docs/templates/public/extensions/themes.html new file mode 100644 index 0000000..5704ff5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/themes.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.themes}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/topSites.html b/chrome/common/extensions/docs/templates/public/extensions/topSites.html new file mode 100644 index 0000000..478945d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/topSites.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.top_sites intro:intros.topSites}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/tts.html b/chrome/common/extensions/docs/templates/public/extensions/tts.html new file mode 100644 index 0000000..08077a5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/tts.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.tts intro:intros.tts}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/ttsEngine.html b/chrome/common/extensions/docs/templates/public/extensions/ttsEngine.html new file mode 100644 index 0000000..a8928cd --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/ttsEngine.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.tts_engine intro:intros.ttsEngine}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/tut_analytics.html b/chrome/common/extensions/docs/templates/public/extensions/tut_analytics.html new file mode 100644 index 0000000..3f967e1 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/tut_analytics.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.tut_analytics}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/tut_debugging.html b/chrome/common/extensions/docs/templates/public/extensions/tut_debugging.html new file mode 100644 index 0000000..0605ef5 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/tut_debugging.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.tut_debugging}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/tut_migration_to_manifest_v2.html b/chrome/common/extensions/docs/templates/public/extensions/tut_migration_to_manifest_v2.html new file mode 100644 index 0000000..a05bfca --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/tut_migration_to_manifest_v2.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.tut_migration_to_manifest_v2}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/tut_oauth.html b/chrome/common/extensions/docs/templates/public/extensions/tut_oauth.html new file mode 100644 index 0000000..d7ba70a --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/tut_oauth.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.tut_oauth}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/tutorials.html b/chrome/common/extensions/docs/templates/public/extensions/tutorials.html new file mode 100644 index 0000000..50bcb7c --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/tutorials.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.tutorials}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/types.html b/chrome/common/extensions/docs/templates/public/extensions/types.html new file mode 100644 index 0000000..1044dff --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/types.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.types intro:intros.types}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/webNavigation.html b/chrome/common/extensions/docs/templates/public/extensions/webNavigation.html new file mode 100644 index 0000000..11d8ac3 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/webNavigation.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.web_navigation intro:intros.webNavigation}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/webRequest.html b/chrome/common/extensions/docs/templates/public/extensions/webRequest.html new file mode 100644 index 0000000..d282267 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/webRequest.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.web_request intro:intros.webRequest}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/webstore.html b/chrome/common/extensions/docs/templates/public/extensions/webstore.html new file mode 100644 index 0000000..728616d --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/webstore.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.webstore}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/whats_new.html b/chrome/common/extensions/docs/templates/public/extensions/whats_new.html new file mode 100644 index 0000000..af165a2 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/whats_new.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.whats_new}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/windows.html b/chrome/common/extensions/docs/templates/public/extensions/windows.html new file mode 100644 index 0000000..8f32cf4 --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/windows.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_api api:apis.windows intro:intros.windows}} diff --git a/chrome/common/extensions/docs/templates/public/extensions/xhr.html b/chrome/common/extensions/docs/templates/public/extensions/xhr.html new file mode 100644 index 0000000..fe158ef --- /dev/null +++ b/chrome/common/extensions/docs/templates/public/extensions/xhr.html @@ -0,0 +1 @@ +{{+partials.standard_extensions_article article:intros.xhr}} |