aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/mozilla/add-ons
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
commit33058f2b292b3a581333bdfb21b8f671898c5060 (patch)
tree51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/mozilla/add-ons
parent8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff)
downloadtranslated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip
initial commit
Diffstat (limited to 'files/zh-cn/mozilla/add-ons')
-rw-r--r--files/zh-cn/mozilla/add-ons/add-on_guidelines/index.html9
-rw-r--r--files/zh-cn/mozilla/add-ons/amo/index.html11
-rw-r--r--files/zh-cn/mozilla/add-ons/amo/policy/contact/index.html28
-rw-r--r--files/zh-cn/mozilla/add-ons/amo/policy/index.html23
-rw-r--r--files/zh-cn/mozilla/add-ons/code_snippets/canvas/index.html237
-rw-r--r--files/zh-cn/mozilla/add-ons/code_snippets/index.html134
-rw-r--r--files/zh-cn/mozilla/add-ons/code_snippets/js_xpcom/index.html97
-rw-r--r--files/zh-cn/mozilla/add-ons/code_snippets/modules/index.html37
-rw-r--r--files/zh-cn/mozilla/add-ons/code_snippets/queryselector/index.html114
-rw-r--r--files/zh-cn/mozilla/add-ons/code_snippets/timers/index.html67
-rw-r--r--files/zh-cn/mozilla/add-ons/creating_custom_firefox_extensions_with_the_mozilla_build_system/index.html470
-rw-r--r--files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox/index.html159
-rw-r--r--files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox_clone/index.html175
-rw-r--r--files/zh-cn/mozilla/add-ons/extension_frequently_asked_questions_move/index.html35
-rw-r--r--files/zh-cn/mozilla/add-ons/extension_packaging/index.html38
-rw-r--r--files/zh-cn/mozilla/add-ons/index.html87
-rw-r--r--files/zh-cn/mozilla/add-ons/install_manifests/index.html363
-rw-r--r--files/zh-cn/mozilla/add-ons/legacy_add_ons/index.html19
-rw-r--r--files/zh-cn/mozilla/add-ons/overlay_extensions/index.html61
-rw-r--r--files/zh-cn/mozilla/add-ons/performance_best_practices_in_extensions/index.html91
-rw-r--r--files/zh-cn/mozilla/add-ons/plugins/index.html116
-rw-r--r--files/zh-cn/mozilla/add-ons/plugins/reference/index.html16
-rw-r--r--files/zh-cn/mozilla/add-ons/plugins/samples_and_test_cases/index.html21
-rw-r--r--files/zh-cn/mozilla/add-ons/plugins/shipping_a_plugin_as_a_toolkit_bundle/index.html56
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/builder/index.html13
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/guides/content_scripts/index.html486
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/guides/index.html115
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/guides/multiprocess_firefox_and_the_sdk/index.html212
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/guides/working_with_events/index.html122
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/high-level_apis/base64/index.html65
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/high-level_apis/clipboard/index.html101
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/high-level_apis/index.html12
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/high-level_apis/notifications/index.html129
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/high-level_apis/panel/index.html899
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/high-level_apis/tabs/index.html669
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/high-level_apis/url/index.html191
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/high-level_apis/widget/index.html839
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/index.html104
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/low-level_apis/index.html26
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/low-level_apis/test_assert/index.html283
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/low-level_apis/ui_button_action/index.html526
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tools/index.html14
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tools/jpm/index.html652
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tools/package_json/index.html312
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/add_a_menu_item_to_firefox/index.html92
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/adding_a_button_to_the_toolbar/index.html83
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/implementing_the_widget/index.html92
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/index.html36
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/overview/index.html54
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/display_a_popup/index.html135
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started/index.html172
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started_(jpm)/index.html162
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/index.html144
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/installation/index.html135
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/l10n/index.html381
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/list_open_tabs/index.html72
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/listen_for_page_load/index.html42
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_the_page_hosted_by_a_tab/index.html109
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_web_pages_based_on_url/index.html210
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/open_a_web_page/index.html52
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/troubleshooting/index.html39
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/unit_testing/index.html102
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/日志/index.html62
-rw-r--r--files/zh-cn/mozilla/add-ons/sdk/tutorials/添加一个菜单项/index.html49
-rw-r--r--files/zh-cn/mozilla/add-ons/setting_up_extension_development_environment/index.html58
-rw-r--r--files/zh-cn/mozilla/add-ons/submitting_an_add-on_to_amo/index.html24
-rw-r--r--files/zh-cn/mozilla/add-ons/themes/index.html65
-rw-r--r--files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/index.html28
-rw-r--r--files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/uuid/index.html6
-rw-r--r--files/zh-cn/mozilla/add-ons/themes/obsolete/index.html10
-rw-r--r--files/zh-cn/mozilla/add-ons/themes/obsolete/theme_changes_in_firefox_3/index.html92
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/add_a_button_to_the_toolbar/index.html220
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/anatomy_of_a_webextension/index.html148
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/alarms/create/index.html127
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/alarms/index.html58
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/bookmarktreenode/index.html81
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/gettree/index.html120
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/index.html128
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/remove/index.html106
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/browseraction/index.html116
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/index.html90
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/onstatechanged/index.html94
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/contentscripts/index.html41
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/contextmenus/index.html191
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/cookies/cookie/index.html121
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/cookies/index.html151
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/devtools.inspectedwindow/index.html72
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/downloads/download/index.html144
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/downloads/downloaditem/index.html101
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/downloads/index.html134
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/find/index.html25
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/history/index.html134
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/history/ontitlechanged/index.html111
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/i18n/index.html85
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/idle/index.html97
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/index.html50
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/permissions/contains/index.html94
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/permissions/index.html93
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/proxy/index.html65
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/connectnative/index.html114
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/getmanifest/index.html79
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/index.html181
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onconnect/index.html228
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onmessage/index.html307
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/openoptionspage/index.html92
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformarch/index.html70
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformos/index.html76
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendmessage/index.html157
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendnativemessage/index.html109
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/search/index.html34
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/search/search/index.html93
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/sessions/index.html136
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/sessions/session/index.html78
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/storage/index.html103
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/tabs/create/index.html137
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/tabs/discard/index.html108
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/tabs/executescript/index.html173
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/tabs/index.html192
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/tabs/insertcss/index.html129
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/tabs/onactivated/index.html110
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/tabs/sendmessage/index.html129
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/tabs/tab/index.html117
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/tabs/查询/index.html179
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/index.html85
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/set/index.html118
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/types/index.html66
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/index.html155
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/ondomcontentloaded/index.html137
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/index.html186
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/requestfilter/index.html71
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/windows/create/index.html169
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/windows/index.html116
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowstate/index.html66
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowtype/index.html65
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/剪切板/index.html36
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/api/剪切板/setimagedata/index.html79
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/browser_support_for_javascript_apis/index.html17
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/chrome_incompatibilities/index.html154
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/content_scripts/index.html575
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/content_security_policy/index.html107
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/embedded_webextensions/index.html205
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/examples/index.html31
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/extending_the_developer_tools/index.html164
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/index.html122
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/interact_with_the_clipboard/index.html157
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/intercept_http_requests/index.html158
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/internationalization/index.html394
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/author/index.html40
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/background/index.html88
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_action/index.html209
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_specific_settings/index.html66
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/content_scripts/index.html216
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/default_locale/index.html42
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/description/index.html43
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/developer/index.html48
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/index.html140
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/manifest_version/index.html45
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/name/index.html43
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/permissions/index.html182
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/short_name/index.html43
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/version/index.html49
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/web_accessible_resources/index.html96
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/manifest.json/主页地址/index.html42
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/match_patterns/index.html384
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/modify_a_web_page/index.html239
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/native_manifests/index.html344
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/native_messaging/index.html326
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/packaging_and_installation/index.html82
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/porting_from_google_chrome/index.html22
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/prerequisites/index.html21
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/publishing_your_webextension/index.html98
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/safely_inserting_external_content_into_a_page/index.html102
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_action/index.html50
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_styles/index.html466
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/user_interface/context_menu_items/index.html48
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/user_interface/devtools_panels/index.html61
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/user_interface/index.html92
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/user_interface/page_actions/index.html93
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/user_interface/侧边栏/index.html53
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/walkthrough/index.html488
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/what_are_webextensions/index.html61
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/what_next_/index.html58
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/working_with_the_tabs_api/index.html634
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/your_first_webextension/index.html238
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/实现一个设置页面/index.html203
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/构建一个跨浏览器的扩展插件/index.html275
-rw-r--r--files/zh-cn/mozilla/add-ons/webextensions/用户界面元素/index.html162
-rw-r--r--files/zh-cn/mozilla/add-ons/working_with_multiprocess_firefox/index.html296
-rw-r--r--files/zh-cn/mozilla/add-ons/雷鸟/index.html131
189 files changed, 26720 insertions, 0 deletions
diff --git a/files/zh-cn/mozilla/add-ons/add-on_guidelines/index.html b/files/zh-cn/mozilla/add-ons/add-on_guidelines/index.html
new file mode 100644
index 0000000000..58b185e048
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/add-on_guidelines/index.html
@@ -0,0 +1,9 @@
+---
+title: 附加组件准则
+slug: Mozilla/Add-ons/Add-on_guidelines
+tags:
+ - add-on
+ - 附加组件
+translation_of: 'https://extensionworkshop.com/documentation/publish/add-on-policies/'
+---
+<p>REDIRECT <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/AMO/Policy/Reviews">https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/AMO/Policy/Reviews</a></p>
diff --git a/files/zh-cn/mozilla/add-ons/amo/index.html b/files/zh-cn/mozilla/add-ons/amo/index.html
new file mode 100644
index 0000000000..0845e54e3d
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/amo/index.html
@@ -0,0 +1,11 @@
+---
+title: AMO
+slug: Mozilla/Add-ons/AMO
+tags:
+ - NeedsTranslation
+ - TopicStub
+translation_of: Mozilla/Add-ons/AMO
+---
+<p>{{AddonSidebar}}</p>
+
+<p>Content to be added.</p>
diff --git a/files/zh-cn/mozilla/add-ons/amo/policy/contact/index.html b/files/zh-cn/mozilla/add-ons/amo/policy/contact/index.html
new file mode 100644
index 0000000000..c847ed92d1
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/amo/policy/contact/index.html
@@ -0,0 +1,28 @@
+---
+title: AMO 联系信息
+slug: Mozilla/Add-ons/AMO/Policy/Contact
+tags:
+ - 附加组件支持
+translation_of: Mozilla/Add-ons#Contact_us
+---
+<p>{{AddonSideBar}}</p>
+
+<p><span id="result_box" lang="zh-CN"><span>感谢您愿意与Mozilla 附加组件小组联络。</span> <span>请仔细阅读此页面,以确保您的请求能到达正确的地方。</span></span></p>
+
+<h4 id="附加组件支持">附加组件支持</h4>
+
+<p><span class="long_text" id="result_box" lang="zh-CN"><span>如果您有关于特定</span></span><span class="long_text" lang="zh-CN"><span>附加组件的支持问题,例如“如何使用此附加组件?”</span> <span>或“为什么不能正常工作?”,请通过附加组件列表页上列出的支持渠道联系该附加组件作者。</span></span></p>
+
+<h4 id="附加组件审查相关">附加组件审查相关</h4>
+
+<p><span class="long_text" id="result_box" lang="zh-CN"><span>如果您有关于附加组件审核希望报告违反政策的问题,请发送电子邮件至</span></span> <a href="mailto:amo-editors@mozilla.org">amo-editors@mozilla.org</a><span class="long_text" lang="zh-CN"><span>。几乎所有的附加组件报告都属于这个类别。请务必包含相关附加组件的链接以及您的问题或评论的详细说明。</span></span></p>
+
+<h4 id="附加组件安全漏洞">附加组件安全漏洞</h4>
+
+<p><span class="long_text" id="result_box" lang="zh-CN"><span>如果您在附加程序中发现了安全漏洞,即使它不在此处托管,Mozilla也对您的发现感兴趣并将与附加开发人员一起尽快更正该问题。</span></span><span><span>附加组件的安全问题可以直接报告</span></span>在 <a href="https://bugzilla.mozilla.org/enter_bug.cgi?product=addons.mozilla.org&amp;component=Add-on%20Security&amp;maketemplate=Add-on%20Security%20Bug&amp;bit-23=1&amp;rep_platform=All&amp;op_sys=All">Bugzilla</a> 的 <a href="http://www.mozilla.org/projects/security/security-bugs-policy.html">confidentially</a> 或发邮件给 <a href="mailto:amo-admins@mozilla.org">amo-admins@mozilla.org</a>.</p>
+
+<h4 id="网站功能与发展"><span><span>网站功能与发展</span></span></h4>
+
+<p><span><span>如果您发现本网站有问题</span></span> , 我们乐意修复。请在Github <a href="https://github.com/mozilla/addons/issues/new">上传BUG报告</a>, 报告中包括问题的位置以及您如何遇到这个问题。</p>
+
+<p><span class="comment seoSummary">关于这些政策或您的插件如何与我们联系。</span></p>
diff --git a/files/zh-cn/mozilla/add-ons/amo/policy/index.html b/files/zh-cn/mozilla/add-ons/amo/policy/index.html
new file mode 100644
index 0000000000..58179ed4fa
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/amo/policy/index.html
@@ -0,0 +1,23 @@
+---
+title: AMO Policies
+slug: Mozilla/Add-ons/AMO/Policy
+tags:
+ - NeedsTranslation
+ - TopicStub
+translation_of: Mozilla/Add-ons/AMO/Policy
+---
+<p>{{AddonSidebar}}</p>
+
+<p>Mozilla 致力于为我们的用户和开发人员确保极佳的附加体验,在提交您的附加组件之前,请查阅下列政策。</p>
+
+<dl>
+ <dd></dd><dt><a href="/Mozilla/Add-ons/AMO/Policy/Agreement">开发者协议</a></dt>
+<dd>Effective January 5, 2016</dd> <dt><a href="/Mozilla/Add-ons/AMO/Policy/Reviews">审核处理</a></dt>
+<dd>Add-ons extend the core capabilities of Firefox, allowing users to modify and personalize their Web experience. A healthy add-on ecosystem, built on trust, is vital for developers to be successful and users to feel safe making Firefox their own. For these reasons, Mozilla requires all add-ons to comply with the following set of policies on acceptable practices. The below is not intended to serve as legal advice, nor is it intended to serve as a comprehensive list of terms to include in your add-on’s privacy policy.</dd><br>
+ <dt><a href="/Mozilla/Add-ons/AMO/Policy/Featured">精选的Add-ons</a></dt>
+<dd>How up-and-coming add-ons become featured and what's involved in the process. </dd><br>
+ <strong><a href="https://developer.mozilla.org/en-US/Add-ons#Contact_us">联系我们</a></strong>
+
+ <p> How to get in touch with us regarding these policies or your add-on.</p>
+
+</dl>
diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/canvas/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/canvas/index.html
new file mode 100644
index 0000000000..002a1b8600
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/code_snippets/canvas/index.html
@@ -0,0 +1,237 @@
+---
+title: Canvas 代码片段
+slug: Mozilla/Add-ons/Code_snippets/Canvas
+translation_of: Archive/Add-ons/Code_snippets/Canvas
+---
+<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;">{{LegacyAddonsNotice}}</span></p>
+
+<p>关于使用<code>&lt;canvas&gt;</code>的一般信息,请参阅 <a class="internal" href="/en-US/docs/Web/API/Canvas_API" title="En/HTML/Canvas">canvas topic page</a>.</p>
+
+<h2 id="网页中可以用到的代码">网页中可以用到的代码</h2>
+
+<h3 id="在画布中获取特定颜色的像素数量">在画布中获取特定颜色的像素数量</h3>
+
+<p>下面的函数将返回画布上颜色(RGB格式)为r、g、b的像素数量。如果用户希望像<a href="https://hacks.mozilla.org/2013/06/building-a-simple-paint-game-with-html5-canvas-and-vanilla-javascript/" title="https://hacks.mozilla.org/2013/06/building-a-simple-paint-game-with-html5-canvas-and-vanilla-javascript/">这篇博客文章</a>中在另一个区域绘画,那么这将非常有用。 </p>
+
+<pre class="brush: js">function getpixelamount(canvas, r, g, b) {
+ var cx = canvas.getContext('2d');
+ var pixels = cx.getImageData(0, 0, canvas.width, canvas.height);
+ var all = pixels.data.length;
+ var amount = 0;
+ for (i = 0; i &lt; all; i += 4) {
+ if (pixels.data[i] === r &amp;&amp;
+ pixels.data[i + 1] === g &amp;&amp;
+ pixels.data[i + 2] === b) {
+ amount++;
+ }
+ }
+ return amount;
+};
+</pre>
+
+<h3 id="在画布中获取某一个像素的颜色">在画布中获取某一个像素的颜色</h3>
+
+<p>下面的代码片段返回一个对象,该对象在画布的x和y的位置上具有RGBA值。这可以用来确定鼠标光标是否在一个特定的形状中。</p>
+
+<pre class="brush: js">function getpixelcolour(canvas, x, y) {
+ var cx = canvas.getContext('2d');
+ var pixel = cx.getImageData(x, y, 1, 1);
+ return {
+ r: pixel.data[0],
+ g: pixel.data[1],
+ b: pixel.data[2],
+ a: pixel.data[3]
+ };
+}
+</pre>
+
+<h3 id="链式调用方法">链式调用方法</h3>
+
+<p>这个类允许可以像jQuery那样链式地访问 2D 渲染上下文的方法和属性 。</p>
+
+<pre class="brush: js">function Canvas2DContext(canvas) {
+ if (typeof canvas === 'string') {
+ canvas = document.getElementById(canvas);
+ }
+ if (!(this instanceof Canvas2DContext)) {
+ return new Canvas2DContext(canvas);
+ }
+ this.context = this.ctx = canvas.getContext('2d');
+ if (!Canvas2DContext.prototype.arc) {
+ Canvas2DContext.setup.call(this, this.ctx);
+ }
+}
+Canvas2DContext.setup = function() {
+ var methods = ['arc', 'arcTo', 'beginPath', 'bezierCurveTo', 'clearRect', 'clip',
+ 'closePath', 'drawImage', 'fill', 'fillRect', 'fillText', 'lineTo', 'moveTo',
+ 'quadraticCurveTo', 'rect', 'restore', 'rotate', 'save', 'scale', 'setTransform',
+ 'stroke', 'strokeRect', 'strokeText', 'transform', 'translate'];
+
+ var getterMethods = ['createPattern', 'drawFocusRing', 'isPointInPath', 'measureText', // drawFocusRing not currently supported
+ // The following might instead be wrapped to be able to chain their child objects
+ 'createImageData', 'createLinearGradient',
+ 'createRadialGradient', 'getImageData', 'putImageData'
+ ];
+
+ var props = ['canvas', 'fillStyle', 'font', 'globalAlpha', 'globalCompositeOperation',
+ 'lineCap', 'lineJoin', 'lineWidth', 'miterLimit', 'shadowOffsetX', 'shadowOffsetY',
+ 'shadowBlur', 'shadowColor', 'strokeStyle', 'textAlign', 'textBaseline'];
+
+ for (let m of methods) {
+ let method = m;
+ Canvas2DContext.prototype[method] = function() {
+ this.ctx[method].apply(this.ctx, arguments);
+ return this;
+ };
+ }
+
+ for (let m of getterMethods) {
+ let method = m;
+ Canvas2DContext.prototype[method] = function() {
+ return this.ctx[method].apply(this.ctx, arguments);
+ };
+ }
+
+ for (let p of props) {
+ let prop = p;
+ Canvas2DContext.prototype[prop] = function(value) {
+ if (value === undefined)
+ return this.ctx[prop];
+ this.ctx[prop] = value;
+ return this;
+ };
+ }
+};
+
+var canvas = document.getElementById('canvas');
+
+// Use context to get access to underlying context
+var ctx = Canvas2DContext(canvas)
+ .strokeStyle('rgb(30, 110, 210)')
+ .transform(10, 3, 4, 5, 1, 0)
+ .strokeRect(2, 10, 15, 20)
+ .context;
+
+// Use property name as a function (but without arguments) to get the value
+var strokeStyle = Canvas2DContext(canvas)
+ .strokeStyle('rgb(50, 110, 210)')
+ .strokeStyle();
+</pre>
+
+<h2 id="Saving_a_canvas_image_to_a_file" name="Saving_a_canvas_image_to_a_file">Code usable only from privileged code</h2>
+
+<p>These snippets are only useful from privileged code, such as extensions or privileged apps.</p>
+
+<h3 id="Saving_a_canvas_image_to_a_file" name="Saving_a_canvas_image_to_a_file">将canvas图片保存到文件中</h3>
+
+<p>The following function accepts a canvas object and a destination file path string. The canvas is converted to a PNG file and saved to the specified location. The function returns a promise which resolves when the file has been completely saved.</p>
+
+<pre class="brush: js">function saveCanvas(canvas, path, type, options) {
+ return Task.spawn(function *() {
+ var reader = new FileReader;
+ var blob = yield new Promise(accept =&gt; canvas.toBlob(accept, type, options));
+ reader.readAsArrayBuffer(blob);
+
+ yield new Promise(accept =&gt; { reader.onloadend = accept });
+
+ return yield OS.File.writeAtomic(path, new Uint8Array(reader.result),
+ { tmpPath: path + '.tmp' });
+ });
+}
+</pre>
+
+<h3 id="Loading_a_remote_page_onto_a_canvas_element" name="Loading_a_remote_page_onto_a_canvas_element">将一个远程页面加载到canvas元素上</h3>
+
+<p>The following class first creates a hidden iframe element and attaches a listener to the frame's load event. Once the remote page has loaded, the remotePageLoaded method fires. This method gets a reference to the iframe's window and draws this window to a canvas object.</p>
+
+<p>Note that this only works if you are running the page from chrome. If you try running the code as a plain webpage, you will get a 'Security error" code: "1000' error.</p>
+
+<pre class="brush: js">RemoteCanvas = function() {
+ this.url = 'http://developer.mozilla.org';
+};
+
+RemoteCanvas.CANVAS_WIDTH = 300;
+RemoteCanvas.CANVAS_HEIGHT = 300;
+
+RemoteCanvas.prototype.load = function() {
+ var windowWidth = window.innerWidth - 25;
+ var iframe;
+ iframe = document.createElement('iframe');
+ iframe.id = 'test-iframe';
+ iframe.height = '10px';
+ iframe.width = windowWidth + 'px';
+ iframe.style.visibility = 'hidden';
+ iframe.src = this.url;
+ // Here is where the magic happens... add a listener to the
+ // frame's onload event
+ iframe.addEventListener('load', this.remotePageLoaded, true);
+ //append to the end of the page
+ window.document.body.appendChild(iframe);
+ return;
+};
+
+RemoteCanvas.prototype.remotePageLoaded = function() {
+ // Look back up the iframe by id
+ var ldrFrame = document.getElementById('test-iframe');
+ // Get a reference to the window object you need for the canvas
+ // drawWindow method
+ var remoteWindow = ldrFrame.contentWindow;
+
+ //Draw canvas
+ var canvas = document.createElement('canvas');
+ canvas.style.width = RemoteCanvas.CANVAS_WIDTH + 'px';
+ canvas.style.height = RemoteCanvas.CANVAS_HEIGHT + 'px';
+ canvas.width = RemoteCanvas.CANVAS_WIDTH;
+ canvas.height = RemoteCanvas.CANVAS_HEIGHT;
+ var windowWidth = window.innerWidth - 25;
+ var windowHeight = window.innerHeight;
+
+ var ctx = canvas.getContext('2d');
+ ctx.clearRect(0, 0,
+ RemoteCanvas.CANVAS_WIDTH,
+ RemoteCanvas.CANVAS_HEIGHT);
+ ctx.save();
+ ctx.scale(RemoteCanvas.CANVAS_WIDTH / windowWidth,
+ RemoteCanvas.CANVAS_HEIGHT / windowHeight);
+ ctx.drawWindow(remoteWindow,
+ 0, 0,
+ windowWidth, windowHeight,
+ 'rgb(255, 255, 255)');
+ ctx.restore();
+};
+</pre>
+
+<p>Usage:</p>
+
+<pre class="brush: js">var remoteCanvas = new RemoteCanvas();
+remoteCanvas.load();
+</pre>
+
+<h3 id="Loading_a_remote_page_onto_a_canvas_element" name="Loading_a_remote_page_onto_a_canvas_element">将图像文件转换为base64字符串</h3>
+
+<p>下面代码加载远程图片,并把它的内容转化为 <code><a href="/en/data_URIs">Data URI scheme</a></code>。</p>
+
+<pre class="brush: js">var canvas = document.createElement('canvas');
+var ctxt = canvas.getContext('2d');
+function loadImageFile(url, callback) {
+ var image = new Image();
+ image.src = url;
+ return new Promise((accept, reject) =&gt; {
+ image.onload = accept;
+ image.onerror = reject;
+ }).then(accept =&gt; {
+ canvas.width = this.width;
+ canvas.height = this.height;
+ ctxt.clearRect(0, 0, this.width, this.height);
+ ctxt.drawImage(this, 0, 0);
+ accept(canvas.toDataURL());
+ });
+}
+</pre>
+
+<p>Usage:</p>
+
+<pre class="brush: js">loadImageFile('myimage.jpg').then(string64 =&gt; { alert(string64); });
+</pre>
+
+<p>如果你想获取本地文件(使用文件选择input元素)的 base64 内容,你必须使用 <code><a href="/en/DOM/FileReader#readAsDataURL%28%29" title="en/DOM/FileReader#readAsDataURL%28%29">FileReader</a></code> 对象。</p>
diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/index.html
new file mode 100644
index 0000000000..bfe77a4e38
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/code_snippets/index.html
@@ -0,0 +1,134 @@
+---
+title: Code snippets
+slug: Mozilla/Add-ons/Code_snippets
+tags:
+ - Add-ons
+ - Code snippets
+ - Extensions
+ - NeedsTranslation
+ - TopicStub
+translation_of: Archive/Add-ons/Code_snippets
+---
+<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;">{{LegacyAddonsNotice}}</span></p>
+
+<p>This is a quick list of useful code snippets (small code samples) available for developers of extensions for the various Mozilla applications. Many of these samples can also be used in XULRunner applications, as well as in actual Mozilla code itself.</p>
+
+<p>These examples demonstrate how to accomplish basic tasks that might not be immediately obvious.</p>
+
+<h2 id="General" name="General">General</h2>
+
+<dl>
+ <dt><a href="/en-US/docs/Code_snippets/From_articles" title="/en-US/docs/Code_snippets/From_articles">Examples and demos from MDN articles</a></dt>
+ <dd>A collection of examples and demos from articles.</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Windows" title="/en-US/docs/Code_snippets/Windows">Window code</a></dt>
+ <dd>Opening and manipulating windows</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Toolbar" title="/en-US/docs/Code_snippets/Toolbar">Toolbar</a></dt>
+ <dd>Toolbar related code</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Sidebar" title="/en-US/docs/Code_snippets/Sidebar">Sidebar</a></dt>
+ <dd>Sidebar related code</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Forms">Forms</a></dt>
+ <dd>Forms related code</dd>
+ <dt><a href="/en-US/docs/Code_snippets/XML" title="/en-US/docs/Code_snippets/XML">XML</a></dt>
+ <dd>Code used to parse, write, manipulate, etc. XML</dd>
+ <dt><a href="/en-US/docs/Code_snippets/File_I_O" title="/en-US/docs/Code_snippets/File_I/O">File I/O</a></dt>
+ <dd>Code used to read, write and process files</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Drag_&amp;_Drop" title="/en-US/docs/Code_snippets/Drag_&amp;_Drop">Drag &amp; Drop</a></dt>
+ <dd>Code used to setup and handle drag and drop events</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Dialogs_and_Prompts" title="/en-US/docs/Code_snippets/Dialogs_and_Prompts">Dialogs</a></dt>
+ <dd>Code used to display and process dialog boxes</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Alerts_and_Notifications" title="/en-US/docs/Code snippets/Alerts and Notifications">Alerts and Notifications </a></dt>
+ <dd>Modal and non-modal ways to notify users</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Preferences" title="/en-US/docs/Code_snippets/Preferences">Preferences</a></dt>
+ <dd>Code used to read, write, and modify preferences</dd>
+ <dt><a href="/en-US/docs/Code_snippets/JS_XPCOM" title="/en-US/docs/Code_snippets/JS_XPCOM">JS XPCOM</a></dt>
+ <dd>Code used to define and call XPCOM components in JavaScript</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Running_applications" title="/en-US/docs/Code_snippets/Running_applications">Running applications</a></dt>
+ <dd>Code used to run other applications</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Canvas" title="/en-US/docs/Code_snippets/Canvas"><code>&lt;canvas&gt;</code> related</a></dt>
+ <dd><a href="/en-US/docs/HTML/Canvas" title="/en-US/docs/HTML/Canvas">WHAT WG Canvas</a>-related code</dd>
+ <dt><a href="/en-US/docs/Signing_a_XPI" title="/en-US/docs/Signing_a_XPI">Signing a XPI</a></dt>
+ <dd>How to sign an XPI with PKI</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Threads">Delayed Execution</a></dt>
+ <dd>Performing background operations.</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Miscellaneous" title="/en-US/docs/Code_snippets/Miscellaneous">Miscellaneous</a></dt>
+ <dd>Miscellaneous useful code fragments</dd>
+ <dt><a href="/en-US/docs/Code_snippets/HTML_to_DOM" title="/en-US/docs/Code_snippets/HTML_to_DOM">HTML to DOM</a></dt>
+ <dd>Using a hidden browser element to parse HTML to a window's DOM</dd>
+</dl>
+
+<h2 id="javascript-libraries" name="javascript-libraries">JavaScript libraries</h2>
+
+<p>Here are some JavaScript libraries that may come in handy.</p>
+
+<dl>
+ <dt><a href="/en-US/docs/Code_snippets/StringView" title="/en-US/docs/Code_snippets/StringView">StringView</a></dt>
+ <dd>A library that implements a <code>StringView</code> view for <a href="/en-US/docs/Web/JavaScript/Typed_arrays" title="/en-US/docs/Web/JavaScript/Typed_arrays">JavaScript typed arrays</a>. This lets you access data in typed arrays using C-like string functions.</dd>
+ <dt><a href="/en-US/Add-ons/Code_snippets/Rosetta" title="/en-US/docs/Code_snippets/Rosetta">Rosetta</a></dt>
+ <dd>By default, the only possible standardized scripting language for HTML is <strong>ECMAScript</strong>. Hence, if you are going to use another scripting language you might expect that most of the browsers will not recognize it. Nevertheless, the increasing computational power of modern browsers together with the introduction of <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays">typed arrays</a> in ECMAScript allow us, in theory, to build full <a class="external external-icon" href="http://en.wikipedia.org/wiki/Virtual_machine">virtual machines</a> in pure ECMAScript. Therefore, it is also possible, in theory, to use ECMAScript for a smaller task: parsing exotic programming languages (i.e., creating compilers). This snippets shows a possible way to start from.</dd>
+</dl>
+
+<h2 id="Browser-oriented_code" name="Browser-oriented_code">Browser-oriented code</h2>
+
+<dl>
+ <dt><a href="/en-US/docs/Code_snippets/Tabbed_browser" title="/en-US/docs/Code_snippets/Tabbed_browser">Tabbed browser code</a> (Firefox/SeaMonkey)</dt>
+ <dd>Basic operations, such as page loading, with the tabbed browser, which is the heart of Mozilla's browser applications</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Cookies" title="/en-US/docs/Code_snippets/Cookies">Cookies</a></dt>
+ <dd>Reading, writing, modifying, and removing cookies</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Page_Loading" title="/en-US/docs/Code_snippets/Page_Loading">Page Loading</a></dt>
+ <dd>Code used to load pages, reload pages, and listen for page loads</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Interaction_between_privileged_and_non-privileged_pages" title="/en-US/docs/Code_snippets/Interaction_between_privileged_and_non-privileged_pages">Interaction between privileged and non-privileged code</a></dt>
+ <dd>How to communicate from extensions to websites and vice-versa.</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Downloading_Files" title="/en-US/docs/Code_snippets/Downloading_Files">Downloading Files</a></dt>
+ <dd>Code to download files, images, and to monitor download progress</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Password_Manager" title="/en-US/docs/Code_snippets/Password_Manager">Password Manager</a></dt>
+ <dd>Code used to read and write passwords to/from the integrated password manager</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Bookmarks" title="/en-US/docs/Code_snippets/Bookmarks">Bookmarks</a></dt>
+ <dd>Code used to read and write bookmarks</dd>
+ <dt><a href="/en-US/docs/Code_snippets/JavaScript_Debugger_Service" title="/en-US/docs/Code_snippets/JavaScript_Debugger_Service">JavaScript Debugger Service</a></dt>
+ <dd>Code used to interact with the JavaScript Debugger Service</dd>
+</dl>
+
+<h2 id="SVG" name="SVG">SVG</h2>
+
+<dl>
+ <dt><a href="/en-US/docs/Code_snippets/SVG_General" title="/en-US/docs/Code_snippets/SVG_General">General</a></dt>
+ <dd>General information and utilities</dd>
+ <dt><a href="/en-US/docs/Code_snippets/SVG_Animation" title="/en-US/docs/Code_snippets/SVG_Animation">SVG Animation</a></dt>
+ <dd>Animate SVG using JavaScript and SMIL</dd>
+ <dt><a href="/en-US/docs/Code_snippets/SVG_Interacting_with_script" title="/en-US/docs/Code_snippets/SVG_Interacting_with_script">SVG Interacting with Script</a></dt>
+ <dd>Using JavaScript and DOM events to create interactive SVG</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Embedding_SVG" title="/en-US/docs/Code_snippets/Embedding_SVG">Embedding SVG in HTML and XUL</a></dt>
+ <dd>Using SVG to enhance HTML or XUL based markup</dd>
+</dl>
+
+<h2 id="XUL_Widgets" name="XUL_Widgets">XUL Widgets</h2>
+
+<dl>
+ <dt><a href="/en-US/docs/Code_snippets/HTML_in_XUL_for_rich_tooltips" title="/en-US/docs/Code_snippets/HTML_in_XUL_for_rich_tooltips">HTML in XUL for Rich Tooltips</a></dt>
+ <dd>Dynamically embed HTML into a XUL element to attain markup in a tooltip</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Label_and_description" title="/en-US/docs/Code_snippets/Label_and_description">Label and description</a></dt>
+ <dd>Special uses and line breaking examples</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Tree" title="/en-US/docs/Code_snippets/Tree">Tree</a></dt>
+ <dd>Setup and manipulation of trees using XUL and JS</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Scrollbar" title="/en-US/docs/Code_snippets/Scrollbar">Scrollbar</a></dt>
+ <dd>Changing style of scrollbars. Applies to scrollbars in browser and iframe as well.</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Autocomplete" title="/en-US/docs/Code_snippets/Autocomplete">Autocomplete</a></dt>
+ <dd>Code used to enable form autocomplete in a browser</dd>
+ <dt><a href="/en-US/docs/Code_snippets/Boxes" title="/en-US/docs/Code_snippets/Boxes">Boxes</a></dt>
+ <dd>Tips and tricks when using boxes as containers</dd>
+ <dt><a class="internal" href="/en-US/docs/Code_snippets/Tabbox" title="/en-US/docs/Code snippets/Tabbox">Tabbox</a></dt>
+ <dd>Removing and manipulating tabs in a tabbox</dd>
+</dl>
+
+<h2 id="Windows-specific" name="Windows-specific">Windows-specific</h2>
+
+<dl>
+ <dt><a href="/en-US/docs/Code_snippets/Finding_Window_Handles" title="/en-US/docs/Code_snippets/Finding_Window_Handles">Finding Window Handles (HWND)</a> (Firefox)</dt>
+ <dd>How to use Windows API calls to find various kinds of Mozilla window handles. Window handles can be used for IPC and Accessibility purposes.</dd>
+ <dt><a href="/en-US/docs/Accessing_the_Windows_Registry_Using_XPCOM" title="/en-US/docs/Accessing_the_Windows_Registry_Using_XPCOM">Using the Windows Registry with XPCOM</a></dt>
+ <dd>How to read, write, modify, delete, enumerate, and watch registry keys and values.</dd>
+</dl>
+
+<h2 id="External_links" name="External_links">External links</h2>
+
+<p>The content at <a class="external" href="http://kb.mozillazine.org/Category:Example_code">MozillaZine Example Code</a> is slowly being moved here, but you can still find useful examples there for now.</p>
diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/js_xpcom/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/js_xpcom/index.html
new file mode 100644
index 0000000000..e5ab2b6189
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/code_snippets/js_xpcom/index.html
@@ -0,0 +1,97 @@
+---
+title: JS XPCOM
+slug: Mozilla/Add-ons/Code_snippets/JS_XPCOM
+translation_of: Archive/Add-ons/Code_snippets/JS_XPCOM
+---
+<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;">{{LegacyAddonsNotice}}</span></p>
+
+<p>这是一些解决XPCOM组件相关的有用的JavaScript代码。</p>
+
+<h3 id="Contract_IDs" name="Contract_IDs">Contract IDs</h3>
+
+<p>契约ID是XPCOM对象独一无二的名字。它们用于创建或者获得XPCOM中的对象。</p>
+
+<h3 id="Interfaces" name="Interfaces">Interfaces</h3>
+
+<p>Every XPCOM object implements one or more interfaces. An interface is simply a list of constants and methods that can be called on the object, an example is <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFile" title="nsIFile is the correct platform-agnostic way to specify a file; you should always use this instead of a string to ensure compatibility.">nsIFile</a></code>. Every XPCOM object must implement the <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/Code_snippets/JS_XPCOM" title="">nsISupports</a></code> interface.</p>
+
+<h3 id="Accessing_XPCOM_components_from_JavaScript" name="Accessing_XPCOM_components_from_JavaScript">Accessing XPCOM components from JavaScript</h3>
+
+<p>XPCOM objects are either created as new instances (each creation gives you a completely new COM object) or as services (each access gives you the same COM object, often called a singleton). Whether you must create a new instance or access as a service depends on the contract. In order to get an XPCOM object you need to know the contract ID of the object and the interface that you wish to use on it.</p>
+
+<h4 id="Creating_an_instance_of_a_component" name="Creating_an_instance_of_a_component">Creating an instance of a component</h4>
+
+<p>The preferred method of creating XPCOM instances is via the <code><a href="/en-US/docs/Components.Constructor">Components.Constructor</a></code> helper. For example,</p>
+
+<pre class="brush: js">var nsFile = Components.Constructor("@mozilla.org/file/local;1", "nsIFile", "initWithPath");
+
+var file = new nsFile(filePath);
+</pre>
+
+<p>They can also be created and initialized manually:</p>
+
+<pre class="brush: js">var file = Components.classes["@mozilla.org/file/local;1"]
+ .createInstance(Components.interfaces.nsIFile);
+file.initWithPath(filePath);
+</pre>
+
+<p>This creates a new instance of the object with contract ID <code>@mozilla.org/file/local;1</code> and allows you to call methods from the <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFile" title="nsIFile is the correct platform-agnostic way to specify a file; you should always use this instead of a string to ensure compatibility.">nsIFile</a></code> interface on it.</p>
+
+<h4 id="Getting_an_XPCOM_service" name="Getting_an_XPCOM_service">Getting an XPCOM service</h4>
+
+<pre class="brush: js">var preferences = Components.classes["@mozilla.org/preferences-service;1"]
+ .getService(Components.interfaces.nsIPrefService);
+</pre>
+
+<p>You can then call any methods in the <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/Code_snippets/JS_XPCOM" title="">nsIPrefService</a></code> interface on the preferences object.</p>
+
+<h4 id="Getting_a_different_interface_for_a_component" name="Getting_a_different_interface_for_a_component">Getting a different interface for a component</h4>
+
+<p>Some components implement more than one interface. Sometimes JavaScript is clever enough to know all the interfaces available on a component, but in most cases you will have to explicitly check for an interface. With the preferences service from the previous example we can do the following:</p>
+
+<pre class="brush: js">var preferences = preferences.QueryInterface(Components.interfaces.nsIPrefBranch2);
+</pre>
+
+<p>This allows you to use the methods in the <code><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/Code_snippets/JS_XPCOM" title="">nsIPrefBranch2</a></code> interface.</p>
+
+<h4 id="Determining_which_interfaces_an_XPCOM_component_supports" name="Determining_which_interfaces_an_XPCOM_component_supports">Determining which interfaces an XPCOM component supports</h4>
+
+<p>To display a list of all interfaces that an XPCOM component supports, do the following:</p>
+
+<pre class="brush: js">// |c| is the XPCOM component instance
+for each (i in Components.interfaces) { if (c instanceof i) { alert(i); } }
+</pre>
+
+<p>In this context, <code>instanceof</code> is the same as <code>QueryInterface</code> except that it returns false instead of throwing an exception when <code>|c|</code> doesn't support interface <code>|i|</code>. Another difference is that <code>QueryInterface</code> returns an object, where as <code>instanceof</code> returns a <code>boolean</code>.</p>
+
+<h3 id="XPCOMUtils_-_About_protocol_handler" name="XPCOMUtils_-_About_protocol_handler">XPCOMUtils - About protocol handler</h3>
+
+<p>{{ Fx_minversion_inline(3) }}This example implements a quick about protocol handler in JS using <a href="/en/XPCOMUtils.jsm" title="en/XPCOMUtils.jsm">XPCOMUtils.jsm</a>.</p>
+
+<pre class="brush: js">Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+function AboutHandler() {}
+AboutHandler.prototype = {
+ newChannel: function(uri) {
+ var channel = Services.io.newChannel("chrome://mystuff/content/mystuff.xul", null, null);
+ channel.originalURI = uri;
+ return channel;
+ },
+ getURIFlags: function(uri) {
+ // Do NOT return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT unless
+ // you make sure to set a non-system principal in newChannel.
+ return 0;
+ },
+
+ classDescription: "About MyStuff Page",
+ classID: Components.ID("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
+ contractID: "@mozilla.org/network/protocol/about;1?what=mystuff",
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule])
+}
+
+var NSGetModule = XPCOMUtils.generateNSGetModule([AboutHandler]);
+}
+</pre>
diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/modules/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/modules/index.html
new file mode 100644
index 0000000000..413e32f59a
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/code_snippets/modules/index.html
@@ -0,0 +1,37 @@
+---
+title: Modules
+slug: Mozilla/Add-ons/Code_snippets/Modules
+translation_of: Archive/Add-ons/Code_snippets/Modules
+---
+<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;"><font><font>{{LegacyAddonsNotice}}</font></font></span></p>
+
+<p><font><font>一些简单的代码将</font></font><a href="/en/JavaScript_code_modules" title="en / JavaScript代码模块"><font><font>JavaScript模块</font></font></a><font><font>转换为非Mozilla特定的代码(例如,如果移植到浏览器)。</font><font>eval()的使用可能不会被关注,因为它仅在</font></font><code>EXPORTED_SYMBOLS</code><font><font> 数组</font><font>上使用,</font><font>而不依赖于用户输入。</font></font></p>
+
+<pre class="brush: js"><font><font>函数importModule(thatObj){</font></font><font><font>
+ thatObj = thatObj || </font><font>窗口;</font></font>
+<font><font>
+ var EXPORTED_SYMBOLS = [</font></font><font><font>
+ //把符号放在这里</font></font><font><font>
+ ]。</font></font>
+<font><font>
+ //你的代码在这里...</font></font>
+<font><font>
+ //在你的代码结尾处:(假设'i'和'thatObj'都没有被导出!)</font></font><font><font>
+ for(var i = 0; i &lt;EXPORTED_SYMBOLS.length; i ++){thatObj [EXPORTED_SYMBOLS [i]] = eval(EXPORTED_SYMBOLS [i]);}</font></font><font><font>
+}</font></font>
+</pre>
+
+<p><font><font>或一次性使用模块:</font></font></p>
+
+<pre class="brush: js"><font><font>(function(thatObj){</font></font><font><font>
+ thatObj = thatObj || </font><font>窗口;</font></font>
+<font><font>
+ var EXPORTED_SYMBOLS = [</font></font><font><font>
+ //把符号放在这里</font></font><font><font>
+ ]。</font></font>
+<font><font>
+ //你的代码在这里...</font></font>
+<font><font>
+ //在你的代码结尾处:(假设'i'和'thatObj'都没有被导出!)</font></font><font><font>
+ for(var i = 0; i &lt;EXPORTED_SYMBOLS.length; i ++){thatObj [EXPORTED_SYMBOLS [i]] = eval(EXPORTED_SYMBOLS [i]);}</font></font><font><font>
+})(); </font><font>//可以在这里放置一个对象参数</font></font></pre>
diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/queryselector/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/queryselector/index.html
new file mode 100644
index 0000000000..364909681f
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/code_snippets/queryselector/index.html
@@ -0,0 +1,114 @@
+---
+title: QuerySelector
+slug: Mozilla/Add-ons/Code_snippets/QuerySelector
+tags:
+ - $
+ - $$
+ - querySelector
+translation_of: Archive/Add-ons/Code_snippets/QuerySelector
+---
+<p> {{ fx_minversion_header(3.5) }}</p>
+
+<p>沿着其他框架,如jQuery或Prototype, 缩短“querySelector”的名称可以很方便:</p>
+
+<pre class="brush: js"> HTMLDocument.prototype.$ = function (selector) {
+  // Only for HTML
+ return this.querySelector(selector);
+ };
+ $(`div`);
+ HTMLDocument.prototype.$$ = function (selector) {
+ // Only for HTML
+ return this.querySelectorAll(selector);
+ };
+ $$(`div`);</pre>
+
+<pre class="brush: js">function $ (selector, el) {
+ if (!el) {el = document;}
+ return el.querySelector(selector);
+}
+function $$ (selector, el) {
+ if (!el) {el = document;}
+ return el.querySelectorAll(selector);
+ // Note: the returned object is a NodeList.
+ // If you'd like to convert it to a Array for convenience, use this instead:
+ // return Array.prototype.slice.call(el.querySelectorAll(selector));
+}
+alert($('#myID').id);
+</pre>
+
+<p>(请注意,在使用火狐浏览器控制台时,上述功能可自动使用.)</p>
+
+<p> XUL 甚至 XML可以很简单的支持(有以下两种替代方法,添加ChromeWindow.prototype 或者 Window.prototype,访问 this.document.querySelector, 或者根据jQuery 风格的链接,即在每个原型的$()方法中返回的‘this'</p>
+
+<pre class="brush: js">HTMLDocument.prototype.$ = function (selector) { // 只用于HTML
+ return this.querySelector(selector);
+};
+
+Example:
+
+&lt;h1&gt;Test!&lt;/h1&gt;
+&lt;script&gt;
+HTMLDocument.prototype.$ = function (selector) {
+ return this.querySelector(selector);
+};
+alert(document.$('h1')); // [object HTMLHeadingElement]
+&lt;/script&gt;
+</pre>
+
+<pre class="brush: js">XULDocument.prototype.$ = function (selector) { // 只用于XUL
+ return this.querySelector(selector);
+};
+
+Example:
+
+&lt;label value="Test!"/&gt;
+&lt;script type="text/javascript"&gt;&lt;![CDATA[
+XULDocument.prototype.$ = function (selector) { // 只用于XUL
+ return this.querySelector(selector);
+};
+
+alert(document.$('label')); // [object XULElement]
+]]&gt;&lt;/script&gt;
+</pre>
+
+<pre class="brush: js">Document.prototype.$ = function (selector) { // 只用于XML
+ return this.querySelector(selector);
+};
+var foo = document.implementation.createDocument('someNS', 'foo', null); // Create an XML document &lt;foo xmlns="someNS"/&gt;
+var bar = foo.createElementNS('someNS', 'bar'); // add &lt;bar xmlns="someNS"/&gt;
+foo.documentElement.appendChild(bar);
+alert(foo.$('bar').nodeName); // gives 'bar'
+</pre>
+
+<pre class="brush: js">Element.prototype.$ = function (selector) { // 可用于HTML,XUL,XML
+ return this.querySelector(selector);
+};
+
+HTML 例子:
+&lt;h1&gt;&lt;a&gt;Test!&lt;a/&gt;&lt;/h1&gt;
+&lt;script&gt;
+Element.prototype.$ = function (selector) {
+ return this.querySelector(selector);
+};
+alert(document.getElementsByTagName('h1')[0].$('a').nodeName); // 'A'
+
+XUL 例子:
+&lt;hbox&gt;&lt;vbox/&gt;&lt;/hbox&gt;
+&lt;script type="text/javascript"&gt;&lt;![CDATA[
+Element.prototype.$ = function (selector) {
+ return this.querySelector(selector);
+};
+var XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
+alert(document.getElementsByTagNameNS(XULNS, 'hbox')[0].$('vbox').nodeName); // vbox
+]]&gt;&lt;/script&gt;
+
+XML 例子:
+&lt;foo xmlns="someNS"&gt;&lt;bar/&gt;&lt;/foo&gt; in document earlier
+var foo = document.getElementsByTagNameNS('someNS', 'foo')[0];
+alert(foo.$('bar'));
+
+</pre>
+
+<p>注意在XML中,  # 'id'选择器将不能体现为'id'属性(因此一个这样名字的属性不一定是XML的ID,尽管他在HTML 和XUL中是这样的), 也不会对 <a href="/en/xml/xml:id" title="en/xml/id">xml:id</a> 起作用.</p>
+
+<p>然而,它将工作于指向没有无前缀属性选择器 (例如'id',但是不是 xml:id: <a class="external" href="http://www.w3.org/TR/selectors-api/#resolving" rel="freelink">http://www.w3.org/TR/selectors-api/#resolving</a>) (即使 CSS3 支持命名空间属性选择器: <a class="external" href="http://www.w3.org/TR/css3-selectors/#attrnmsp" rel="freelink">http://www.w3.org/TR/css3-selectors/#attrnmsp</a> 以及可能将xml:id 当作 #: <a class="external" href="http://www.w3.org/TR/css3-selectors/#id-selectors" rel="freelink">http://www.w3.org/TR/css3-selectors/#id-selectors</a> ).</p>
diff --git a/files/zh-cn/mozilla/add-ons/code_snippets/timers/index.html b/files/zh-cn/mozilla/add-ons/code_snippets/timers/index.html
new file mode 100644
index 0000000000..f15f127f61
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/code_snippets/timers/index.html
@@ -0,0 +1,67 @@
+---
+title: JavaScript timers
+slug: Mozilla/Add-ons/Code_snippets/Timers
+translation_of: Archive/Add-ons/Code_snippets/Timers
+---
+<p><span style="color: #000000; display: inline !important; float: none; font-family: Cantarell; font-size: 14.666666984558105px; font-style: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal;">{{LegacyAddonsNotice}}</span></p>
+
+<p> </p>
+
+<p>JavaScript的代码块通常情况下是顺序执行的。不过有几个JavaScript内置函数(计时器),能够让我们推迟任意指令的执行:</p>
+
+<ul>
+ <li>{{domxref("window.setTimeout","setTimeout()")}}</li>
+ <li>{{domxref("window.setInterval","setInterval()")}}</li>
+ <li>{{domxref("window.setImmediate","setImmediate()")}}</li>
+ <li>{{domxref("window.requestAnimationFrame","requestAnimationFrame()")}}</li>
+</ul>
+
+<p>The <code>setTimeout()</code> function is commonly used if you wish to have your function called <em>once</em> after the specified delay. The <code>setInterval()</code> function is commonly used to set a delay for functions that are executed again and again, such as animations. The <code>setImmediate()</code> function can be used instead of the <code>setTimeout(<em>fn</em>, <strong>0</strong>)</code> method to execute heavy operations in IE. The <code>requestAnimationFrame()</code> function tells the browser that you wish to perform an animation and requests that the browser schedule a repaint of the window for the next animation frame.</p>
+
+<h2 class="Documentation" id="Documentation" name="Documentation">Documentation</h2>
+
+<dl>
+ <dt>{{domxref("window.setTimeout","setTimeout()")}}</dt>
+ <dd>Calls a function or executes a code snippet after specified delay.</dd>
+ <dt>{{domxref("window.setInterval","setInterval()")}}</dt>
+ <dd>Calls a function or executes a code snippet repeatedly, with a fixed time delay between each call to that function.</dd>
+ <dt>{{domxref("window.setImmediate","setImmediate()")}}</dt>
+ <dd>Calls a function immediately after the browser has completed other operations, such as events and display updates.</dd>
+ <dt>{{domxref("window.clearTimeout","clearTimeout()")}}</dt>
+ <dd>Clears the delay set by <code>setTimeout()</code>.</dd>
+ <dt>{{domxref("window.clearInterval","clearInterval()")}}</dt>
+ <dd>Cancels repeated action which was set up using <code>setInterval()</code>.</dd>
+ <dt>{{domxref("window.clearImmediate","clearImmediate()")}}</dt>
+ <dd>Cancels the immediate actions, just like {{domxref("window.clearTimeout","clearTimeout()")}} for {{domxref("window.setTimeout","setTimeout()")}}.</dd>
+ <dt><a href="/en-US/docs/Web/JavaScript/Timers/Daemons">Using JavaScript timers within animations (Javascript Daemons Management)</a></dt>
+ <dd>In Computer science a <em>daemon</em> is a task that runs as a background process, rather than being under the direct control of an interactive user. In JavaScript programming language, all <em>daemons</em> are processes created by JavaScript timers or by a {{domxref("Worker")}} instantiation. Here are some code snippets which simplify and abstract the management of daemons.</dd>
+ <dt>{{domxref("window.requestAnimationFrame","requestAnimationFrame()")}}</dt>
+ <dd><code>requestAnimationFrame()</code> tells the browser that you wish to perform an animation and requests that the browser schedule a repaint of the window for the next animation frame. The method takes as an argument a callback to be invoked before the repaint.</dd>
+ <dt>{{domxref("performance.now","performance.now()")}}</dt>
+ <dd>
+ <p><code>performance.now()</code> returns a timestamp, measured in milliseconds, accurate to one thousandth of a millisecond. This timestamp is equal to the number of milliseconds since the <code>navigationStart </code>attribute of the <a href="/en-US/docs/Navigation_timing" title="/en-US/docs/Navigation_timing"><code>performance.timing</code></a> interface.</p>
+ </dd>
+ <dt><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now"><code>Date.now()</code></a></dt>
+ <dd><code>Date.now()</code> returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.</dd>
+ <dt><a href="/en-US/docs/Web/Guide/Performance/Using_web_workers#Timeouts_and_intervals">Using JavaScript timers within workers</a></dt>
+ <dd>Workers can use timeouts and intervals just like the main thread can. This can be useful, for example, if you want to have your worker thread run code periodically instead of nonstop.</dd>
+ <dt><a href="/en-US/docs/Web/Guide/Needs_categorization/Functions_available_to_workers">Functions available to workers</a></dt>
+ <dd>In addition to the standard JavaScript set of functions (such as String, Array, Object, JSON etc), there are a variety of functions available from the DOM to workers. This article provides a list of those.</dd>
+ <dt><a href="/en-US/docs/Web/HTML/Canvas/Tutorial/Basic_animations">Basic animations</a></dt>
+ <dd>Since we're using script to control canvas elements it's also very easy to make (interactive) animations. Unfortunately the canvas element was never designed to be used in this way (unlike Flash) so there are limitations.</dd>
+ <dt><a href="/en-US/docs/Mozilla/JavaScript_code_modules/Timer.jsm" title="/en-US/docs/Mozilla/JavaScript_code_modules/Timer.jsm">Timer.jsm</a></dt>
+ <dd>The <code>Timer.jsm</code> JavaScript code module contains pure-JavaScript implementations of <a href="/en-US/docs/DOM/window.setTimeout" title="/en-US/docs/DOM/window.setTimeout"><code>setTimeout </code></a>and <a href="/en-US/docs/DOM/window.clearTimeout" title="/en-US/docs/DOM/window.clearTimeout"><code>clearTimeout</code></a> that are compatible with the DOM window functions, but that can be used by code that does not have access to a DOM window (for example, <a href="/en-US/docs/Mozilla/JavaScript_code_modules" title="/en-US/docs/Mozilla/JavaScript_code_modules">JavaScript code modules </a>or <a href="/en-US/docs/The_message_manager" title="/en-US/docs/The_message_manager">content frame scripts</a>).</dd>
+</dl>
+
+<h2 id="See_also">See also</h2>
+
+<ul>
+ <li><a href="/en-US/docs/Web/API/window.setTimeout#Callback_arguments">Callback arguments polyfill</a></li>
+ <li><a href="/en-US/docs/Web/API/window.setInterval#A_little_framework">A little <code>setInterval</code> framework</a></li>
+ <li><a href="/en-US/docs/Web/JavaScript">JavaScript</a>, <a href="/en-US/docs/Web/Guide/Performance/Using_web_workers">Workers</a></li>
+ <li><a href="/en-US/docs/Web/Guide/Performance/Using_web_workers">Using web workers</a></li>
+ <li>{{domxref("window.performance")}}</li>
+ <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date"><code>Date</code></a></li>
+</ul>
+
+<p>&lt;embed height="0" id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd" type="application/thunder_download_plugin" width="0"&gt;</p>
diff --git a/files/zh-cn/mozilla/add-ons/creating_custom_firefox_extensions_with_the_mozilla_build_system/index.html b/files/zh-cn/mozilla/add-ons/creating_custom_firefox_extensions_with_the_mozilla_build_system/index.html
new file mode 100644
index 0000000000..617d86487c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/creating_custom_firefox_extensions_with_the_mozilla_build_system/index.html
@@ -0,0 +1,470 @@
+---
+title: Creating Custom Firefox Extensions with the Mozilla Build System
+slug: >-
+ Mozilla/Add-ons/Creating_Custom_Firefox_Extensions_with_the_Mozilla_Build_System
+translation_of: >-
+ Archive/Add-ons/Creating_Custom_Firefox_Extensions_with_the_Mozilla_Build_System
+---
+<div class="note">
+ <strong>Note:</strong> All instructions in this article apply to the Mozilla 1.8 branch only (i.e. Firefox 1.5). I'll try to keep it up-to-date as the trunk changes, but you certainly should not assume that this will work with the 1.7 branch (i.e. Firefox 1.0) or older.</div>
+<p>There is a <a href="/en/Extensions" title="en/Extensions">wealth of material</a> on creating extensions for Firefox. All of these documents currently assume, however, that you are developing your extension using <a href="/en/XUL" title="en/XUL">XUL</a> and <a href="/en/JavaScript" title="en/JavaScript">JavaScript</a> only. For complex extensions, it may be necessary to create components in C++ that provide additional functionality. Reasons why you might want to include C++ components in your extension include:</p>
+<p>有大量如何创建扩展的资料, 但是这些文档都假定仅仅使用XUL和Javascript开发扩展. 对于复杂的扩展, 可能需要C++开发相关的功能代码. 下列原因可能使你想要在扩展中包括C++组件(Components):</p>
+<ul>
+ <li>Need for high-performance beyond what can be delivered by JavaScript code.</li>
+ <li>性能要求高, Javascript达不到要求</li>
+ <li>Use of third-party libraries written in C or C++.</li>
+ <li>需要使用第三方C/C++库</li>
+ <li>Use of Mozilla interfaces that are not exposed via <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a> (e.g. <a href="/en/NSPR" title="en/NSPR">NSPR</a>).</li>
+ <li>使用Mozilla接口,不仅仅是XPCOM提供的接口</li>
+</ul>
+<p>This article describes how to set up the development environment for a large, complex Firefox extension with any or all of the above-mentioned requirements. The process of garnering this information has been somewhat painful due to the lack of published information on this topic, but has been assisted by the contributions of various members of the Mozilla development community, who have shown extraordinary patience in fielding ignorant newbie questions. I can’t stress enough that I’m far from a Mozilla expert, though I’m getting better. There may be much in this document that is inaccurate, misleading or just plain wrong. In fact, one of my goals in writing this is to fine-tune these instructions until they constitute a definite guide for hardcore hackers who want to extend the Firefox platform. If you’re one of the many people who know more about this than I do, your help in improving this article would be greatly appreciated.</p>
+<p>I should also stress that you do <em>not</em> have to build Mozilla or use the Mozilla build system if you want to create C++ components for Mozilla. If you are just looking to create an <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a> component or two, this is probably overkill, and you might want to take a look at <a class="external" href="http://www.iosart.com/firefox/xpcom/">this guide</a> instead. On the other hand, if you are an experienced developer or team, and you know that you are going to build a large, complex extension, you would do well to consider the approach described in this article.</p>
+<p>One final note: I’ve only tried these techniques inside Firefox, but they’ll probably work more or less unchanged on other Gecko-based platforms like Thunderbird or Seamonkey. If someone can confirm this and/or provide guidelines for what’s different, I’ll update the article to incorporate this information.</p>
+<h3 id="Bambi_Meets_Mozilla(小鹿斑比遇见Mozilla)">Bambi Meets Mozilla(小鹿斑比遇见Mozilla)</h3>
+<p>None of this is for the faint of heart. In particular, the initial step involves building Mozilla, which is a huge - nay, gargantuan! - project. Many intelligent developers have been driven to the brink of insanity trying to build it for the first time. If you're not an experienced C++ developer, I wouldn’t even bother. Stick to JavaScript.</p>
+<p>(小鹿斑比小时候很胆小)其实这些并不适合胆小者. 尤其是, 第一步编译Mozilla, 那是庞大的 -- 非常非常巨大的 -- 项目. 在初次编译Mozilla时, 许多聪明的开发者都快被逼疯了. 如果你不是资深的C++开发者, 就别烦恼了, 继续玩Javascript.</p>
+<h4 id="On_Windows_Platforms">On Windows Platforms</h4>
+<p>The first time I built Mozilla I used <a href="/En/Developer_Guide/Build_Instructions/Windows_Prerequisites" title="En/Developer_Guide/Build_Instructions/Windows_Prerequisites">this guide</a>. I can’t even remember why anymore, but I got stuck in a number of places, and the whole affair ended up taking far longer than I originally expected. Much furniture was smashed, much hair torn out by the roots. Here’s a <a class="external" href="http://whereswalden.com/mozilla/msvcfree/">comprehensive looking guide</a> that’s gotten good reviews. Follow every step methodically and you’ll probably be alright. Focus on the fact that once you get the build working, it’ll probably work effortlessly from then on. Maybe.</p>
+<h4 id="On_Other_Platforms">On Other Platforms</h4>
+<p>On other platforms, namely Linux and MacOS, the process is much easier. All the tools for building are available built-in, and therefore all you have to do is run some commands in the terminal. You can find full instructions for almost any OS <a href="/En/Developer_Guide/Build_Instructions" title="En/Developer_Guide/Build_Instructions">here</a>.</p>
+<h3 id="Structuring_Your_Project(构造您的项目)">Structuring Your Project(构造您的项目)</h3>
+<p>Mozilla includes a number of complex extensions that are integrated into its build process. It has thus been necessary to solve all of the issues involved in creating and registering XPCOM components, building JAR files and manifests, installing the lot into the Firefox <code>extensions/</code> directory and so forth. So it behooves us to piggyback on this infrastructure to build our extension.</p>
+<p>First of all, think of a catchy name for your extension and create a directory with that name under the <code>/mozilla/extensions/</code> directory. Use only lowercase letters. You should see a bunch of other directories (<code>inspector/</code>, <code>reporter/</code> and so forth) at the same level in the build tree.</p>
+<p>Note that before actually building anything, the Mozilla build system invokes a configuration process that generates the actual makefiles used for the build from makefile templates called <code>Makefile.in</code>. The actual makefiles tend to be very similar or identical to the templates, but the extra flexibility gained from having the makefiles generated dynamically is one of the things that makes the build system so powerful.</p>
+<h4 id="Anatomy_of_a_Simple_C_Extension(分析一个简单的C扩展)">Anatomy of a Simple C++ Extension(分析一个简单的C++扩展)</h4>
+<p>We assume that you are using C++ to write XPCOM components that can be used either from other C++ components or from JavaScript. The process of creating a component is actually relatively straightforward when the Mozilla build system is used.</p>
+<p>In the simplest case, a component will consist of a single main directory with two subdirectories, <code>public/</code> and <code>src/</code>. The main directory and each subdirectory must contain a <code>Makefile.in</code> (from now on I’ll just refer to this file as a makefile although we know that it is actually used to generate the real makefile). This makefile says two things. First of all, it lists the subdirectories that make up the extension, so the build system knows where to look for additional makefiles. Secondly, it instructs the build system to create a new extension, rather than copying the components directly into Firefox’s binary directory. The main advantage of using an extension is that it is easy to package everything up and install it on another machine.</p>
+<p>So here’s your basic, plain-vanilla top-level makefile (<code>Makefile.in</code> in the main extension directory):</p>
+<pre>DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = myextension
+
+DIRS = public src
+
+XPI_NAME = myextension
+INSTALL_EXTENSION_ID = myextension@mycompany.com
+XPI_PKGNAME = myextension
+
+DIST_FILES = install.rdf
+
+include $(topsrcdir)/config/rules.mk
+</pre>
+<p>A detailed description of the make process, describing the key features of this makefile, can be found <a href="/en/How_Mozilla's_build_system_works" title="en/How_Mozilla's_build_system_works">here</a>. <strong>MODULE</strong> and <strong>XPI_NAME</strong> are both set to the name of your extension; they should be repeated in all project makefiles so that all of the files land in the same place in the XPI staging area (see below). <strong>INSTALL_EXTENSION_ID</strong> is the unique ID of your extension. This can be a GUID, but the format shown above is prettier and, let’s face it, a lot easier to remember. You don’t have to provide an <strong>XPI_PKGNAME</strong>, but if you do an XPI file, suitable for distribution, is automatically created in the root of the XPI staging area (<code>/mozilla/$(MOZ_OBJDIR)/dist/xpi-stage/</code>).</p>
+<p>Every extension must include an <code>install.rdf</code> file that tells Firefox how to install it. This file should be located in the main extension directory and look something like this:</p>
+<pre>&lt;?xml version="1.0"?&gt;
+
+&lt;RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#"&gt;
+ &lt;Description about="urn:mozilla:install-manifest"&gt;
+ &lt;em:id&gt;myextension@mycompany.com&lt;/em:id&gt;
+ &lt;em:version&gt;0.1&lt;/em:version&gt;
+
+ &lt;em:targetApplication&gt;
+ &lt;!-- Firefox --&gt;
+ &lt;Description&gt;
+ &lt;em:id&gt;{ec8030f7-c20a-464f-9b0e-13a3a9e97384}&lt;/em:id&gt;
+ &lt;em:minVersion&gt;1.0+&lt;/em:minVersion&gt;
+ &lt;em:maxVersion&gt;1.0+&lt;/em:maxVersion&gt;
+ &lt;/Description&gt;
+ &lt;/em:targetApplication&gt;
+
+ &lt;!-- front-end metadata --&gt;
+ &lt;em:name&gt;My First Extension&lt;/em:name&gt;
+ &lt;em:description&gt;Just an example.&lt;/em:description&gt;
+ &lt;em:creator&gt;allpeers.com&lt;/em:creator&gt;
+ &lt;em:homepageURL&gt;http://www.allpeers.com/blog/&lt;/em:homepageURL&gt;
+ &lt;/Description&gt;
+&lt;/RDF&gt;
+</pre>
+<p>There's a <a href="/en/Install_Manifests" title="en/Install_Manifests">detailed description</a> of the format of the <code>install.rdf</code> file. Use the <strong>DIST_FILES</strong> variable in the makefile to tell <code>make</code> to copy the file into the extension directory and (optional) XPI file.</p>
+<h4 id="Public_Interfaces(公共接口)">Public Interfaces(公共接口)</h4>
+<p>The <code>public/</code> directory contains any interfaces that need to be accessed by other modules. These can be <a class="external" href="http://www.mozilla.org/scriptable/xpidl/idl-authors-guide/index.html">IDL</a> files describing <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a> interfaces, which are used to generate normal C++ header files for inclusion in your source files. They can also be normal C++ header files that are to be used directly by other modules. The easiest way to accomplish the latter is to use inline implementations for all methods so you don’t have any additional linking dependencies. Otherwise you will have to link statically to your module if you use these public headers in other modules. Personally I would discourage this practice (among other things, static linking means the same code gets loaded more than once into memory, and the code won’t be available from JavaScript or other non-C++ languages) and encourage the use of XPCOM wherever possible.</p>
+<p>The makefile in the <code>public/</code> directory should follow this model:</p>
+<pre>DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = myextension
+XPIDL_MODULE = myextension
+
+XPI_NAME = myextension
+
+EXPORTS = \
+ myHeader.h \
+ $(NULL)
+
+XPIDLSRCS = \
+ myIFirstComponent.idl \
+ myISecondComponent.idl \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+</pre>
+<p><strong>XPIDL_MODULE</strong> is the name of the generated XPT file that contains type information about your <a class="external" href="http://www.mozilla.org/scriptable/xpidl/idl-authors-guide/index.html">IDL</a> interfaces. If you have multiple modules, make absolutely sure that you use a different value for <strong>XPIDL_MODULE</strong> for each one. Otherwise the first module’s XPT file will be overwritten by the second and you’ll get <strong>NS_ERROR_XPC_BAD_IID</strong> errors when you try to access its IDL interfaces from your code. The files under <strong>EXPORTS</strong> are copied directly to the <code>/mozilla/$(MOZ_OBJDIR)/dist/include/myextension/</code> directory and are thus accessible from other modules (the value of <strong>MOZ_OBJDIR</strong> is defined in <code>/mozilla/.mozconfig</code>). XPIDLSRCS are run through the IDL processor, and the generated C++ headers are copied into the same include directory. In addition, an XPT (type library) file is generated and placed in the <code>components/</code> subdirectory of your extension.</p>
+<h4 id="Source_Files(源文件)">Source Files(源文件)</h4>
+<p>Now it’s time to create the makefile and source files in the <code>src/</code> subdirectory. If you're implementing interfaces that you've described using IDL, the easiest way to do this is to leave the <code>src/</code> directory empty and run <code>make</code> on the <code>public/</code> directory only; this will be explained shortly.</p>
+<p>Then open the generated header file for your interface from <code>/mozilla/$(MOZ_OBJDIR)/dist/include/myextension/</code>. It contains stubs for the component .H and .CPP files that you can copy and paste into your implementation files. All you have to do is fill in the implementation stubs in the C++ file and you’re good to go.</p>
+<p>Here’s an example of the makefile you need to place into your <code>src</code> directory:</p>
+<pre class="eval">DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+IS_COMPONENT = 1
+<a href="/en/MODULE" title="en/MODULE">MODULE</a> = myextension
+<a href="/en/LIBRARY_NAME" title="en/LIBRARY_NAME">LIBRARY_NAME</a> = myExtension
+<a href="/en/USE_STATIC_LIBS" title="en/USE_STATIC_LIBS">USE_STATIC_LIBS</a> = 1
+
+XPI_NAME = myextension
+
+REQUIRES = xpcom \
+ string \
+ $(NULL)
+
+<a href="/en/CPPSRCS" title="en/CPPSRCS">CPPSRCS</a> = \
+ myFirstComponent.cpp \
+ mySecondComponent.cpp \
+ myExtension.cpp \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+<a href="/en/EXTRA_DSO_LDOPTS" title="en/EXTRA_DSO_LDOPTS">EXTRA_DSO_LDOPTS</a> += \
+ $(XPCOM_GLUE_LDOPTS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+# <span class="highlightred">NOTE: If you are coding against the 1.8.0 branch (not 1.8 branch or trunk), the</span>
+# <span class="highlightred">above line won't work, due to linker flag issues.</span> Use the following
+# variables instead:
+#
+# EXTRA_DSO_LDOPTS += \
+# $(MOZ_COMPONENT_LIBS) \
+# $(NULL)
+#
+# Unfortunately, using MOZ_COMPONENT_LIBS links against xpcom_core, which means
+# your components will not work in future versions of Firefox.
+</pre>
+<p>The <code>REQUIRES</code> section tells <code>make</code> which modules your components uses. This causes the relevant subdirectories of <code>/mozilla/$(MOZ_OBJDIR)/dist/include/</code> to be added to the C++ compiler's include path. If you’re including Mozilla headers and the compiler isn’t finding them, it could well mean that you haven’t listed all of the necessary modules here. <code>CPPSRCS</code> lists the source files that need to be built.</p>
+<p>In this example, the first two files contain the implementation of the extension’s two components. The final file, <code>myExtension.cpp</code>, contains the code necessary to register these components, as described in the next section.</p>
+<h4 id="Registering_Your_Components(注册组件)">Registering Your Components(注册组件)</h4>
+<p>In order to use your components from other C++ modules and JavaScript, you first have to register them. To do this, your extension needs to implement a class that exposes the <code><a href="/en/XPCOM_Interface_Reference/nsIModule" title="en/XPCOM_Interface_Reference/nsIModule">nsIModule</a></code> interface, which has methods for accessing the components defined in a module. Luckily, this can be accomplished through the use of a few simple macros, so you don’t have to concern yourself with the messy details of what’s happening under the hood.</p>
+<p>The first step is to define a CID, contract ID and class name for each of your components. Place the following code (adapting the <strong>#defines</strong> accordingly) into the header of each component that you want to be able to instantiate using the component manager:</p>
+<pre>// {00000000-0000-0000-0000-000000000000}
+#define MYFIRSTCOMPONENT_CID \
+ { 0x00000000, 0x0000, 0x0000, \
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }
+
+#define MYFIRSTCOMPONENT_CONTRACTID "@mycompany.com/myfirst;1"
+#define MYFIRSTCOMPONENT_CLASSNAME "My First Component"
+</pre>
+<p>Obviously you need to fill in the CID with a real GUID. Under Windows, this can be generated using <a class="external" href="http://www.microsoft.com/downloads/details.aspx?familyid=94551F58-484F-4A8C-BB39-ADB270833AFC">guidgen.exe</a>. Unix people can use uuidgen (comes standard with most unixes and Linux distros).</p>
+<p>Now create the <code>myExtension.cpp</code> file like so:</p>
+<pre>#include "nsXPCOM.h"
+
+#include "nsIGenericFactory.h"
+
+/**
+ * Components to be registered
+ */
+#include "myFirstComponent.h"
+#include "mySecondComponent.h"
+
+NS_GENERIC_FACTORY_CONSTRUCTOR(myFirstComponent)
+NS_GENERIC_FACTORY_CONSTRUCTOR(mySecondComponent)
+
+//----------------------------------------------------------
+
+static const nsModuleComponentInfo components[] =
+{
+ {
+ MYFIRSTCOMPONENT_CLASSNAME,
+ MYFIRSTCOMPONENT_CID,
+ MYFIRSTCOMPONENT_CONTRACTID,
+ myFirstComponentConstructor
+ },
+ {
+ MYSECONDCOMPONENT_CLASSNAME,
+ MYSECONDCOMPONENT_CID,
+ MYSECONDCOMPONENT_CONTRACTID,
+ mySecondComponentConstructor
+ },
+};
+
+NS_IMPL_NSGETMODULE(MyExtension, components)
+</pre>
+<p>The <strong>NS_IMPL_NSGETMODULE</strong> macro creates the appropriate module object providing access to all of the components listed in the <code><a href="/en/NsModuleComponentInfo" title="en/NsModuleComponentInfo">nsModuleComponentInfo</a></code> array.</p>
+<h4 id="Building_It(编译扩展)">Building It(编译扩展)</h4>
+<p>As mentioned above, you’ll probably want to build your extension immediately after creating your IDL files in order to generate the C++ stubs for your component implementations. I’m assuming that you’ve already built Firefox successfully. If not, return immediately to the beginning of this article and don’t come back til you have a functioning <code>firefox.exe</code>. Do not pass go. Do not collect $200.</p>
+<p>Still here? Okay, now we have to modify your <code>.mozconfig</code> (in the <code>/mozilla/</code> root directory) so that your extension is built along with Mozilla. Add the following line at the end of the file:</p>
+<pre>ac_add_options --enable-extensions=default,myextension
+</pre>
+<p>Now launch <code>make</code> from the Mozilla root:</p>
+<pre>make -f client.mk build
+</pre>
+<p>Even if you have an up-to-date Firefox build, you’ll have to wait a while for <code>make</code> to recurse over the entire Mozilla source tree looking for new stuff (on my machine, which is pretty fast, this takes a good 10-15 minutes). Eventually it will reach your extension and generate a bunch of stuff under <code>/mozilla/$(MOZ_OBJDIR)/</code>:</p>
+<ul>
+ <li>Exported header files and generated header files (from IDL) in <code>dist/include/myextension/</code></li>
+ <li>Static libraries for your modules in <code>dist/lib/</code> (in case other modules want to link statically to your stuff instead of using XPCOM).</li>
+ <li>XPI file in <code>dist/xpi-stage/myextension.xpi</code>.</li>
+ <li>Generated makefiles for your projects in <code>extensions/myextension/</code> (remember, we’re under <code>/mozilla/$(MOZ_OBJDIR)/</code>.</li>
+ <li>Everything else in <code><a class="link-mailto" href="mailto:dist/bin/extensions/myextension@mycompany.com" rel="freelink">dist/bin/extensions/myextension@mycompany.com</a>/</code>.</li>
+</ul>
+<p>A lot of this stuff won’t get created on this first pass since <code>make</code> will gag when it doesn’t find the source files for your components. Don’t worry about this; all you need are the generated header files that contain the C++ implementation stubs. Go back and flesh out the C++ implementation of your components so that the build can complete next time. Remember that you should never, ever modify any of these generated files. Always modify the files used to generate them and rerun <code>make</code>. There might be exceptions to this rule, but if you’re changing the generated files directly, you’re probably doing something wrong.</p>
+<p>The process of walking the entire Mozilla tree takes a long time. If you already have a Mozilla build, you can avoid this by creating a makefile for your extension directly. Go to the root of your $(MOZ_OBJDIR) and (from a bash-compatible shell) enter:</p>
+<pre class="eval">../build/autoconf/make-makefile extensions/myextension
+</pre>
+<p>If your $(MOZ_OBJDIR) is located outside your $(TOPSRCDIR), you'll need to do:</p>
+<pre class="eval">$(TOPSRCDIR)/build/autoconf/make-makefile -t $(TOPSRCDIR) extensions/myextension
+</pre>
+<p>in order for the script to know where your source is (it'll use the extension path you gave it relative to the current dir to figure out where you want your makefiles to go).</p>
+<p>This will generate the proper makefile for your extension. Whether you build the whole Mozilla tree or take this shortcut, you can build from now on by going to <code>/mozilla/$(MOZ_OBJDIR)/extensions/myextension/</code> and typing "make" on the command line. It should build your component without bothering with the rest of Mozilla. If everything works out, you’ll see your XPI file in the XPI staging area. You’ll also see the "exploded" version of the XPI (i.e. the unzipped directory structure) underneath <code>/mozilla/$(MOZ_OBJDIR)/dist/bin/extensions</code>. (If something goes wrong, figure out what, fix it and then come back here and add it to this article.)</p>
+<p>To make sure that the build really finished, launch Firefox and check that your extension is listed when you select Tools/Extensions. If you are using Firefox as your regular browser (and if you’re not, why not!?), you might be annoyed by the fact that you have to close regular Firefox before running your custom-built version. If so, try setting the <strong>MOZ_NO_REMOTE</strong> environment variable to "1" before running the development version of Firefox. You’ll also need to use a different profile for your development version:</p>
+<pre class="eval">firefox -P <em>development</em>
+</pre>
+<p>Where <em>development</em> is replaced with the name of the extra profile you’ve created. This will let you run both versions of Firefox simultaneously, saving you oodles of time over the course of the build/test cycle.</p>
+<h4 id="No_Place_Like_Chrome">No Place Like Chrome</h4>
+<p>Yippee-ki-yay! Now you have an extension that does, well, absolutely nothing. It’s time to do something with those groovy components that you’ve implemented and registered. The simplest way to do this is to write some <a href="/en/JavaScript" title="en/JavaScript">JavaScript</a> and <a href="/en/XUL" title="en/XUL">XUL</a> code. At this point, it would be very helpful to have a bit of experience <a href="/en/Extensions" title="en/Extensions">writing "regular" extensions</a> (i.e. without using custom C++ components). If you’ve never done this, I strongly recommend that you think of a cool idea for something simple that you’ve always wanted to tweak in Firefox and write it. Just displaying a new menu item that opens a "Hello, World!" dialog box would be already be a great exercise to get warmed up with.</p>
+<p>Assuming you know how to write XUL/JavaScript extensions, you’re aware that the most important stuff goes in the <code>chrome/</code> directory of your extension. Well, the fact that you’re also using C++ components doesn’t change that one whit. So now you need to create the normal <code>content/</code>, <code>locale/</code> and <code>skin/</code> directories in which to place your chrome files. Personally I like placing these directly under the root directory of my module, but I don’t suppose it makes any difference if you prefer putting them under a <code>chrome/</code> subdirectory or whatever. Let freedom reign!</p>
+<p>Once you’ve written the necessary chrome files (for instance, an overlay that adds a menu item to instantiate and use one of your components), you need to package them up as part of your extension. This is accomplished through the use of a <a href="/en/JAR_Manifests" title="en/JAR_Manifests">JAR Manifest</a>. For our simple extension example, this file might look something like this:</p>
+<pre>myextension.jar:
+% content myextension %content/
+% locale myextension en-US %locale/en-US/
+% skin myextension classic/1.0 %skin/classic/
+% overlay chrome://browser/content/browser.xul chrome://myextension/content/MyExtensionOverlay.xul
+ content/MyExtensionOverlay.js (content/MyExtensionOverlay.js)
+ content/MyExtensionOverlay.xul (content/MyExtensionOverlay.xul)
+ locale/en-US/MyExtension.dtd (locale/en-US/MyExtension.dtd)
+ locale/en-US/MyExtension.properties (locale/en-US/MyExtension.properties)
+ skin/classic/MyExtension.css (skin/classic/MyExtension.css)
+</pre>
+<p>Place this code in a file called <code>jar.mn</code> in the root directory of your extension, making sure that the paths in parentheses point to actual files (when interpreted relative to the root directory). You also have to make one small change to the makefile in the same directory, adding the following line:</p>
+<pre class="eval">USE_EXTENSION_MANIFEST = 1
+</pre>
+<p>This tells <code>make</code> to create a single manifest file called <code>chrome.manifest</code> instead of creating separate manifests with goofy names for each package.</p>
+<p>Now launch <code>make</code> again, and you should see a <code>chrome</code> subdirectory appear in your extension (<code>/mozilla/$(MOZ_OBJDIR)<a class="link-mailto" href="mailto:/dist/bin/extensions/myextension@mycompany.com" rel="freelink">/dist/bin/extensions/myextension@mycompany.com</a>/</code>). Note that the <code>chrome</code> directory contains a JAR (i.e. ZIP) file with all the chrome files listed in <code>jar.mn</code> as well as a complete directory structure mirroring that of the JAR file. The directory structure, however, is empty. Why? I don’t know. Don’t worry about this, the files in the JAR are the ones that are actually used.</p>
+<h4 id="Keeping_it_Complex">Keeping it Complex</h4>
+<p>If you’re developing a really complex extension with lots of <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a> components, you’ll probably want to divide your code up into smaller modules.</p>
+<h5 id="Kinda_Sorta_Complex_Extensions">Kinda, Sorta Complex Extensions</h5>
+<p>For a moderately complex extension, it’s probably enough just to subdivide the code into a single level of modules. Let’s assume that you have a <code>base/</code> module that defines a bunch of basic XPCOM components and an <code>advanced/</code> module that defines some chrome as well as other components that use the basic components. Your complete directory structure will look something like this:</p>
+<ul>
+ <li>myextension
+ <ul>
+ <li>base
+ <ul>
+ <li>public</li>
+ <li>src</li>
+ </ul>
+ </li>
+ <li>advanced
+ <ul>
+ <li>content</li>
+ <li>locale
+ <ul>
+ <li>en-US</li>
+ <li>...other locales...</li>
+ </ul>
+ </li>
+ <li>public</li>
+ <li>skin
+ <ul>
+ <li>classic</li>
+ <li>...other skins...</li>
+ </ul>
+ </li>
+ <li>src</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+<p>Other than that, nothing really changes. The makefiles in the <code>base/</code> and <code>advanced/</code> directories should look more or less like your original root makefile, remembering to change the <strong>DEPTH</strong> variable to account for the fact that they’ve moved a level further away from the Mozilla root. You also need to remove the <strong>DIST_FILES</strong> variable since that’s going to be in the top-level makefile. Every makefile that generates anything should define the <strong>XPI_NAME</strong> variable to make sure generated files go into your extension and not into the global <code>components/</code> directory. In fact, just define this in every makefile to be safe. You can use the same <strong>MODULE</strong> in both <code>base/</code> and <code>advanced/</code> so that all the generated include files go into the same directory, but make sure that you don’t use the same <strong>XPIDL_MODULE</strong> in the two <code>public/</code> directories or one of the component type libraries (i.e. XPT files) will overwrite the other one and all hell will break loose.</p>
+<p>Each module must also have a different value for the <strong>LIBRARY_NAME</strong> variable. This is the name of the generated dynamic library, so if we call the libraries "myBase" and "myAdvanced", we’ll end up with <code>myBase.dll</code> and <code>myAdvanced.dll</code> (on Windows, at least). And each of these modules is going to have a separate C++ file for registering components. So there will be two files that look like <code>myExtension.cpp</code> in the original example, say <code>Base.cpp</code> and <code>Advanced.cpp</code>. Finally, each module will obviously have its own <code>jar.mn</code>, though they can reference the same JAR filename and package name if you want all the chrome files to be organized in a single JAR file and package. The only file that really stays put is <code>install.rdf</code>, which still exists once and only once in the extension root directory.</p>
+<p>As for the top-level makefile, it will now look like this:</p>
+<pre>DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = myextension
+
+DIRS = base advanced
+
+XPI_NAME = myextension
+INSTALL_EXTENSION_ID = myextension@mycompany.com
+XPI_PKGNAME = myextension
+
+DIST_FILES = install.rdf
+
+include $(topsrcdir)/config/rules.mk
+</pre>
+<h5 id="Seriously_Complex_Extensions">Seriously Complex Extensions</h5>
+<p>At some point, even a single module may grow to the point where you want to divide it further into submodules. The difference between having separate modules and having a single module with separate submodules is that the submodules all share the same file for registering components (the famous <code>myExtension.cpp</code> file), and when compiled they create a single dynamic library. The decision to split a module into submodules is all about code organization; it doesn’t really affect the final product at all.</p>
+<p>To split a module into submodules, first create a subdirectory for each submodule. Then create an additional directory called <code>build/</code>. Each submodule will be configured to create a static library, and the <code>build/</code> directory will pull these libraries together to create a single dynamic component library. Confused? Here’s an example, showing just the <code>advanced/</code> subbranch of the <code>myextension/</code> directory:</p>
+<ul>
+ <li>advanced
+ <ul>
+ <li>build</li>
+ <li>intricate
+ <ul>
+ <li>public</li>
+ <li>src</li>
+ </ul>
+ </li>
+ <li>multifarious
+ <ul>
+ <li>public</li>
+ <li>src</li>
+ </ul>
+ </li>
+ <li>content</li>
+ <li>locale
+ <ul>
+ <li>en-US</li>
+ <li>...other locales...</li>
+ </ul>
+ </li>
+ <li>skin
+ <ul>
+ <li>classic</li>
+ <li>...other skins...</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+<p>As you can see, we’ve split <code>advanced/</code> into two submodules: <code>intricate/</code> and <code>multifarious/</code>, and we’ve added an additional <code>build/</code> subdirectory. We’ve left the chrome directories directly under <code>advanced/</code>, since they aren’t tied to any specific submodule. This means that <code>jar.mn</code> will stay in the same place.</p>
+<p>The <code>intricate/</code> and <code>multifarious/</code> makefiles will look a lot like the original <code>advanced/</code> makefile, but we’ll need to tweak them a bit. As always, we have to adjust the <strong>DEPTH</strong> variable since the makefiles are deeper in the directory structure. And we should change the <strong>LIBRARY_NAME</strong> to indicate that we’re generating a static library for each submodule. By convention the "_s" suffix is used for this purpose. So let’s call them "myIntricate_s" and "myMultifarious_s". Finally, we define the variable <strong>FORCE_STATIC_LIB</strong>, resulting in a makefile that starts something like this:</p>
+<pre>DEPTH = ../../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = myextension
+LIBRARY_NAME = myIntricate_s
+FORCE_STATIC_LIB = 1
+USE_STATIC_LIBS = 1
+
+XPI_NAME = myextension
+
+...more stuff here...
+</pre>
+<p>The <code>build</code> makefile pulls together the static libraries generated by the submodules and creates a single (dynamic) component library:</p>
+<pre>DEPTH = ../../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+IS_COMPONENT = 1
+MODULE = myextension
+LIBRARY_NAME = myAdvanced
+USE_STATIC_LIBS = 1
+
+XPI_NAME = myextension
+
+DEFINES += XPCOM_GLUE
+
+SHARED_LIBRARY_LIBS = \
+ $(DIST)/lib/$(LIB_PREFIX)myIntricate_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)myMultifarious_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)xpcom.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)nspr4.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)plds4.$(LIB_SUFFIX) \
+ $(DIST)/lib/$(LIB_PREFIX)plc4.$(LIB_SUFFIX) \
+ $(NULL)
+
+REQUIRES = \
+ xpcom \
+ string \
+ $(NULL)
+
+CPPSRCS = \
+ Advanced.cpp \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+LOCAL_INCLUDES += \
+ -I$(srcdir)/../intricate/src \
+ -I$(srcdir)/../multifarious/src \
+ $(NULL)
+</pre>
+<p>The makefile in the <code>advanced/</code> directory should list the <code>intricate/</code>, <code>multifarious/</code> and <code>build/</code> directories in its <strong>DIRS</strong> variable. Make sure that <code>build/</code> comes last since it can’t create the component library until the other makefiles have completed.</p>
+<h3 id="Other_Topics">Other Topics</h3>
+<h4 id="Adding_Data_Files_to_Your_Extensions">Adding Data Files to Your Extensions</h4>
+<p>In some cases, you may wish to include additional files in your extension that don’t belong in the <code>chrome/</code> subdirectory. Examples might be database files or XML schemas. This can be achieved by adding a custom step to your makefile that copies the files from the source tree into the extension’s target directory.</p>
+<h5 id="Copying_Data_Files_Into_Target_Directory">Copying Data Files Into Target Directory</h5>
+<p>Let’s say that you have some data files containing statistical information that you want to include in your extension and make available to your components. You’ve placed these files, which have the extension .TXT, into a <code>stats/</code> subdirectory under your extension directory in the source tree. The following makefile rule can be used to copy these files into the final target directory of the extension:</p>
+<pre>export::
+ if test ! -d $(FINAL_TARGET)/stats; then \
+ $(NSINSTALL) -D $(FINAL_TARGET)/stats; \
+ fi
+ $(INSTALL) $(srcdir)/*.txt $(FINAL_TARGET)/stats
+</pre>
+<h5 id="Accessing_Data_Files_From_Components">Accessing Data Files From Components</h5>
+<p>The trick to accessing your data files is to figure out where the home directory of your extension is. Rumor has it that at some future date, this will possible through the <code><a href="/en/XPCOM_Interface_Reference/nsIExtensionManager" title="en/XPCOM_Interface_Reference/nsIExtensionManager">nsIExtensionManager</a></code> interface or something similar. In the meantime, there is a simple and reliable hack that can be used to achieve this. In the implementation of any JavaScript XPCOM component, there is a special <strong>__LOCATION__</strong> (two leading and two trailing underscores) symbol that points to the component’s implementation file. So you can write a simple component which deduces the root directory of your extensions by extrapolating from its location.</p>
+<p><a class="external" href="http://www.builderau.com.au/program/soa/Creating_XPCOM_components_with_JavaScript/0,39024614,39206503,00.htm">This article</a> explains how to create an XPCOM component in JavaScript. You’ll need an IDL file for an interface that looks something like this:</p>
+<pre>interface myILocation : nsISupports
+{
+ readonly attribute nsIFile locationFile;
+};
+</pre>
+<p>Place the IDL file in the <code>public/</code> directory of your project or subproject. In the <code>src/</code> directory, place the JavaScript file that implements the component. The component implementation will include the methods for retrieving the path or file for the extension’s home directory:</p>
+<pre>myLocation.prototype =
+{
+ QueryInterface: function(iid)
+ {
+ if (iid.equals(nsISupports))
+ return this;
+ if (iid.equals(myILocation))
+ return this;
+
+ Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
+ return null;
+ },
+
+ get locationFile()
+ {
+ return __LOCATION__.parent.parent;
+ }
+}
+</pre>
+<p>This assumes that the component resides in a subdirectory of the extension directory (by convention, this directory is called <code>components/</code>). The <code>parent</code> property of <strong>__LOCATION__</strong> returns the <code>components/</code>, and the <code>parent</code> of this is the extension directory.</p>
+<p>The last step is to modify the makefile of the source directory where you placed your JavaScript file so that it is copied into the appropriate location in the extension:</p>
+<pre>export::
+ $(INSTALL) $(srcdir)/*.js $(FINAL_TARGET)/components
+</pre>
+<p>Now you can instantiate an instance of this component and use the <code>locationFile</code> property to get an <code><a href="/en/XPCOM_Interface_Reference/nsIFile" title="en/XPCOM_Interface_Reference/nsIFile">nsIFile</a></code> interface that points to your extension’s home directory.</p>
+<h4 id="Using_Third-Party_Libraries">Using Third-Party Libraries</h4>
+<p>For more sophisticated extensions, you may want to integrate third-party libraries that provide specialized functionality for database connectivity, image processing, networking and the like. If you want your extension to run on all Firefox platforms, you will need to have the source code for the library in question, so I assume that this is available.</p>
+<p>The most convenient approach from the perspective of the development cycle is to create a Mozilla-style makefile for the library. This works well for libraries that have a straightforward make process without extensive configuration. A good example of this is the SQLite library included in the Mozilla build tree at <code>db/sqlite</code>. By adapting the makefile in this way, the library is created as part of the standard Mozilla build process, which eliminates additional build steps. The downside is that you will need to update the modified makefile any time a new version of the library is released.</p>
+<p>For libraries that have complex configuration processes, use a non-standard compiler or have other special characteristics, it may be unfeasible to create a Mozilla-compliant makefile. In this case, I would recommend placing the entire library distribution inside the project or subproject that uses it. So if library <code>acmelib</code> is used inside the <code>multifarious/</code> subproject in the above example, it would be placed as a subdirectory underneath that subproject (at the same level as <code>public/</code> and <code>src/</code>).</p>
+<p>Of course, this means that you will have to build <code>acmelib</code> manually on all platforms before launching the Mozilla build. But at least you can then refer to include files and import libraries from your component using relative paths.</p>
+<h4 id="Building_for_Multiple_Platforms">Building for Multiple Platforms</h4>
+<p>TODO</p>
+<div class="originaldocinfo">
+ <h2 id="Original_Document_Information">Original Document Information</h2>
+ <ul>
+ <li>Author: Matthew Gertner - July 26, 2005.</li>
+ <li>Permission granted to migrate in Jan 2006, including permission to relicense under the CC:By-SA.</li>
+ <li>Original Source: <a class="external" href="http://www.allpeers.com/blog/creating-complex-firefox-extensions/" rel="freelink">http://www.allpeers.com/blog/creatin...ox-extensions/</a></li>
+ </ul>
+</div>
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox/index.html b/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox/index.html
new file mode 100644
index 0000000000..b03cc689c9
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox/index.html
@@ -0,0 +1,159 @@
+---
+title: 为 Firefox 创建 OpenSearch 插件
+slug: Mozilla/Add-ons/Creating_OpenSearch_plugins_for_Firefox
+translation_of: Web/OpenSearch
+---
+<p>{{ fx_minversion_header("2") }}</p>
+<p><a href="/en/Firefox_2_for_developers" title="en/Firefox_2_for_developers">Firefox 2</a> 支持使用 <a class="external" href="http://opensearch.org/">OpenSearch</a> 格式开发搜索引擎插件. 使用 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document">OpenSearch 格式</a>开发能够在IE 7 以及 Firefox上实现兼容. 这是这种语法被推荐使用的原因.</p>
+<p>Firefox 也支持不被包括在 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document">OpenSearch格式</a>  中的其它的搜索功能,例如搜索建议(search suggestion)以及 <code>SearchForm</code> 元素. 这篇文章主要关注创建与OpenSearch格式兼容的支持额外的firefox特殊特征的搜索插件.</p>
+<p>OpenSearch 描述文件也能被如在 <a href="#Autodiscovery_of_search_plugins">Autodiscovery of search plugins</a>  中描述的一样被advertised(道歉这里不知如何翻译) ,并且能够如在 <a href="/en/Adding_search_engines_from_web_pages" title="en/Adding_search_engines_from_web_pages">Adding search engines from web pages</a>中所说的进行编程安装.</p>
+<h2 id="OpenSearch_描述文件">OpenSearch 描述文件</h2>
+<p>遵循以下的模板,你就会发现通过 XML 文件写一个搜索引擎实际上是如此的简单。 粗体字部分需要根据具体你所写的搜索引擎需要来进行定制 。</p>
+<pre class="brush: xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+ xmlns:moz="http://www.mozilla.org/2006/browser/search/"&gt;
+ &lt;ShortName&gt;<strong>engineName</strong>&lt;/ShortName&gt;
+ &lt;Description&gt;<strong>engineDescription</strong>&lt;/Description&gt;
+ &lt;InputEncoding&gt;<strong>inputEncoding</strong>&lt;/InputEncoding&gt;
+ &lt;Image width="16" height="16" type="image/x-icon"&gt;data:image/x-icon;base64,<strong>imageData</strong>&lt;/Image&gt;
+ &lt;Url type="text/html" method="<strong>method</strong>" template="<strong>searchURL</strong>"&gt;
+ &lt;Param name="<strong>paramName1</strong>" value="<strong>paramValue1</strong>"/&gt;
+ ...
+ &lt;Param name="<strong>paramNameN</strong>" value="<strong>paramValueN</strong>"/&gt;
+ &lt;/Url&gt;
+ &lt;Url type="application/x-suggestions+json" template="<strong>suggestionURL</strong>"/&gt;
+ &lt;moz:SearchForm&gt;<strong>searchFormURL</strong>&lt;/moz:SearchForm&gt;
+&lt;/OpenSearchDescription&gt;</pre>
+<dl>
+ <dt>
+ <strong>ShortName</strong></dt>
+ <dd>
+ 对搜索引擎的简称</dd>
+ <dd>
+ <strong>限制:</strong> 名称仅能包含16个字符以下的纯文本. 名称不能包含HTML标志或其他标志.</dd>
+</dl>
+<dl>
+ <dt>
+ <strong>Description</strong></dt>
+ <dd>
+ 对于搜索引擎的简单描述</dd>
+ <dd>
+ <strong>限制:</strong> 描述仅能包含少于1024个字符的纯文本.  名称不能包含HTML标志或其他标志.</dd>
+</dl>
+<dl>
+ <dt>
+ <strong>InputEncoding</strong></dt>
+ <dd>
+ 向搜索引擎所输内容的字符编码.例如: <code>&lt;InputEncoding&gt;UTF-8&lt;/InputEncoding&gt;</code>.</dd>
+</dl>
+<dl>
+ <dt>
+ <strong>Image</strong></dt>
+ <dd>
+ 使用指向一个图标的URL来代表这个搜索引擎. 可能的话, 应提供16x16大小的"image/x-icon"类型的图像以及一个64x64大小的 "image/jpeg" 或 "image/png"类型的图像. 链接也可以使用 <a class="external" href="http://en.wikipedia.org/wiki/Data:_URI_scheme">data: URI scheme</a>.  <a class="external" href="http://software.hixie.ch/utilities/cgi/data/data">The data: URI kitchen</a>在这能找到一个能有效地帮助你构建写在此处的数据的工具.
+ <pre class="eval">&lt;Image height="16" width="16" type="image/x-icon"&gt;<a class="external" href="http://example.com/favicon.ico" rel="freelink">http://example.com/favicon.ico</a>&lt;/Image&gt;
+  OR
+&lt;Image height="16" width="16"&gt;data:image/x-icon;base64,AAABAAEAEBAAA ... DAAA=&lt;/Image&gt;
+</pre>
+ Firefox以base64编码的data: URI (搜索插件被保存在 profile中的 "searchplugins" 文件夹) 缓存此图标. 当这完成时, http: URIs 被改变为 data: URIs.</dd>
+</dl>
+<dl>
+ <dt>
+ <strong>Url</strong></dt>
+ <dd>
+ 描述用来实现搜索请求的一个或多个URL.  <code>method</code> 属性决定使用 <code>GET</code> 还是 <code>POST</code>请求来获取返回的数据. <code>template</code> 属性指定实现搜索请求的 URL.</dd>
+ <dd>
+ <div class="note">
+ <strong>注意:</strong> IE7 不支持 <code>POST</code> 请求.</div>
+ </dd>
+</dl>
+<dl>
+ <dd>
+ 这是两种firefox支持的URL类型:</dd>
+</dl>
+<ul>
+ <li><code>type="text/html"</code> 用来指定进行搜索查询的URL.</li>
+ <li><code>type="application/x-suggestions+json"</code> 用来指定获取搜索建议(search suggestions)的URL.</li>
+</ul>
+<dl>
+ <dd>
+ 这两种URL任何一种你都能使用 <code>{searchTerms}</code>来替换用户在搜索栏中输入的搜索内容. 其他支持的动态搜索参数可见 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_3#OpenSearch_1.1_parameters">OpenSearch 1.1 parameters</a>.</dd>
+</dl>
+<dl>
+ <dd>
+ 对使用搜索建议查询来说,  URL template用来获取JSON格式的建议列表. 若需要知道关于如何在服务器上实现搜索建议支持, 请见 <a href="/en/Supporting_search_suggestions_in_search_plugins" title="en/Supporting_search_suggestions_in_search_plugins">Supporting search suggestions in search plugins</a>.</dd>
+</dl>
+<p><img alt="Image:SearchSuggestionSample.png" class="internal" src="/@api/deki/files/358/=SearchSuggestionSample.png"></p>
+<dl>
+ <dt>
+ <strong>Param</strong></dt>
+ <dd>
+ 这个参数用来包括那些需要和搜索查询一起被传递的作为键值对的参数.<code> 你能使用{searchTerms}</code>来指代用户输入的搜索条目.</dd>
+ <dd>
+ <div class="note">
+ <strong>注意:</strong> IE7不支持此元素.</div>
+ </dd>
+</dl>
+<dl>
+ <dt>
+ <strong>SearchForm</strong></dt>
+ <dd>
+ 跳往搜索页的 URL. 这使得Firefox能让用户直接浏览目的网站.</dd>
+ <dd>
+ <div class="note">
+ <strong>注意:</strong> 这个元素是firefox限定的, 并不是 OpenSearch 的一部分, 我们在例子中使用 "<code>moz:</code>" XML命名前缀来确保其它的不支持此元素的用户代理能安全地忽略此元素.</div>
+ </dd>
+</dl>
+<h2 id="自动搜寻搜索插件">自动搜寻搜索插件</h2>
+<p>提供搜索插件的网站能宣传自己以使firefox使用者能容易地下载并安装此插件.</p>
+<p>要支持自动搜寻 你仅需在 你网页的<code>&lt;head&gt;</code> 中加上一条:</p>
+<pre class="eval">&lt;link rel="search" type="application/opensearchdescription+xml" title="<em>searchTitle</em>" href="<em>pluginURL</em>"&gt;
+</pre>
+<p>斜体字部分解释如下:</p>
+<dl>
+ <dt>
+ <strong>searchTitle</strong></dt>
+ <dd>
+ 搜索的名称, 如 "Search MDC" or "Yahoo! Search". 这个值应该与你在插件文件中的ShortName相一致.</dd>
+</dl>
+<dl>
+ <dt>
+ <strong>pluginURL</strong></dt>
+ <dd>
+ 指向 XML搜索插件的URL, 能让浏览者下载插件.</dd>
+</dl>
+<p>如果你的网站提供多个插件, 你能为他们每一个都支持自动搜寻功能. 例如:</p>
+<pre class="eval">&lt;link rel="search" type="application/opensearchdescription+xml" title="MySite: By Author" href="<a class="external" href="http://www.mysite.com/mysiteauthor.xml" rel="freelink">http://www.mysite.com/mysiteauthor.xml</a>"&gt;
+&lt;link rel="search" type="application/opensearchdescription+xml" title="MySite: By Title" href="<a class="external" href="http://www.mysite.com/mysitetitle.xml" rel="freelink">http://www.mysite.com/mysitetitle.xml</a>"&gt;
+</pre>
+<p>这样,你的网站提供的插件就能同时以作者和名称分别作为搜索条目而被搜索.</p>
+<h2 id="为_OpenSearch_插件支持自动更新">为 OpenSearch 插件支持自动更新</h2>
+<p>{{ fx_minversion_note("3.5", "This section covers a feature introduced in Firefox 3.5.") }}</p>
+<p>从Firefox 3.5开始, OpenSearch 插件能够自动更新.  要支持这个, 需要包括一个额外的 "<code>application/opensearchdescription+xml</code>"类型<code>Url</code> 元素.  <code>rel</code>属性需要设为 "<code>self</code>" , template 属性需要是指向能自动更新的OpenSearch文档的 URL.</p>
+<p>例如:</p>
+<pre>&lt;Url type="application/opensearchdescription+xml"
+     rel="self"
+     template="http://www.foo.com/mysearchdescription.xml" /&gt;
+</pre>
+<div class="note">
+ <strong>注意:</strong>  <a class="external" href="http://addons.mozilla.org" title="http://addons.mozilla.org/">addons.mozilla.org</a> (AMO) 不支持 OpenSearch 插件的自动更新. 如果你想将你的插件发布在 AMO上, 你不应该使用自动更新.</div>
+<h2 id="排错指南">排错指南</h2>
+<p>如果你的搜索插件有错误, 当在firefox2中添加插件时会出错. 然而,错误信息可能并不是完全有所帮助的, 因此接下来的建议能帮你发现问题.</p>
+<ul>
+ <li>你的服务器应当运行使用MIME类型为<code>application/opensearchdescription+xml的</code> OpenSearch 插件.</li>
+ <li>确保你的搜索插件正确地格式化了. 你能通过直接将插件加载入firefox来检查.  template URL 中的&amp;符号需要使用 &amp;amp代替;标签需要以斜杠或是相匹配的结束标志结束。</li>
+ <li><code>xmlns</code>属性是很重要的, 没有了他你会得到 "Firefox could not download the search plugin from: (URL)"错误信息.</li>
+ <li>注意你必须包含一个 <code>text/html</code> URL — 仅包含 Atom 或 <a href="/en/RSS" title="en/RSS">RSS</a> URL 类型 (有效但firefox不支持)的插件将产生  "could not download the search plugin"错误.</li>
+ <li>远程获取的收藏夹图标大小不能超过10KB (见 {{ Bug(361923) }}).</li>
+</ul>
+<p>另外, 搜索插件服务提供了日志机制,这对于插件开发者来说可能能起到一定作用 . 使用 <em>about:config</em> 设定 '<code>browser.search.log</code>' 为 <code>true</code>. 插件被加载后日志信息将显示在火狐的 <a href="/en/Error_Console" title="en/Error_Console">Error Console</a> 中(Tools-&gt;Error Console).</p>
+<h2 id="参考资料">参考资料</h2>
+<ul>
+ <li><a class="external" href="http://opensearch.org/">OpenSearch Documentation</a>, <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0">OpenSearch Documentation about the Url and Param element</a></li>
+ <li>Technorati.com has a <a class="external" href="http://technorati.com/osd.xml">working osd.xml</a></li>
+ <li>More on Autodiscovery difficulties at bugzilla {{ Bug(340208) }}</li>
+ <li><a class="external" href="http://en.wikipedia.org/wiki/Data:_URI_scheme"><code>data:</code> URI scheme</a></li>
+ <li><a class="external" href="http://www.searchplugins.net">searchplugins.net</a> - create OpenSearch plugins for use with Firefox 2. <a class="external" href="http://www.searchplugins.net/pluginlist.aspx">List of generated search plugins</a></li>
+ <li><a class="external" href="http://keijisaito.info/ready2search/e/">Ready2Search</a> - create OpenSearch plugins. <a class="external" href="http://keijisaito.info/arc/search/en_make_plugin.htm">Customized Search through Ready2Search</a></li>
+</ul>
+<p>{{ languages( { "es": "es/Creación_de_plugins_OpenSearch_para_Firefox", "de": "de/OpenSearch_Plugin_für_Firefox_erstellen", "ca": "ca/Creació_de_connectors_OpenSearch_per_al_Firefox", "fr": "fr/Création_de_plugins_OpenSearch_pour_Firefox", "ja": "ja/Creating_OpenSearch_plugins_for_Firefox", "pl": "pl/Tworzenie_wtyczek_OpenSearch_dla_Firefoksa", "pt": "pt/Criando_plugins_OpenSearch_para_o_Firefox" } ) }}</p>
diff --git a/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox_clone/index.html b/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox_clone/index.html
new file mode 100644
index 0000000000..5c511cc132
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/creating_opensearch_plugins_for_firefox_clone/index.html
@@ -0,0 +1,175 @@
+---
+title: 为 Firefox 创建 OpenSearch 插件
+slug: Mozilla/Add-ons/Creating_OpenSearch_plugins_for_Firefox_clone
+tags:
+ - 定制
+ - 搜索
+---
+<p>{{ fx_minversion_header("2") }}</p>
+
+<p><a href="/en/Firefox_2_for_developers" title="en/Firefox_2_for_developers">Firefox 2</a> 支持使用 <a class="external" href="http://opensearch.org/">OpenSearch</a> 格式开发搜索引擎插件. 使用 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document">OpenSearch 格式</a>开发能够在IE 7 以及 Firefox上实现兼容. 这是这种语法被推荐使用的原因.</p>
+
+<p>Firefox 也支持不被包括在 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1#OpenSearch_description_document">OpenSearch格式</a>  中的其它的搜索功能,例如搜索建议(search suggestion)以及 <code>SearchForm</code> 元素. 这篇文章主要关注创建与OpenSearch格式兼容的支持额外的firefox特殊特征的搜索插件.</p>
+
+<p>OpenSearch 描述文件也能被如在 <a href="#Autodiscovery_of_search_plugins">Autodiscovery of search plugins</a>  中描述的一样被advertised(道歉这里不知如何翻译) ,并且能够如在 <a href="/en/Adding_search_engines_from_web_pages" title="en/Adding_search_engines_from_web_pages">Adding search engines from web pages</a>中所说的进行编程安装.</p>
+
+<h2 id="OpenSearch_描述文件">OpenSearch 描述文件</h2>
+
+<p>遵循以下的模板,你就会发现通过 XML 文件写一个搜索引擎实际上是如此的简单。 粗体字部分需要根据具体你所写的搜索引擎需要来进行定制 。</p>
+
+<pre class="brush: xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+ xmlns:moz="http://www.mozilla.org/2006/browser/search/"&gt;
+ &lt;ShortName&gt;<strong>engineName</strong>&lt;/ShortName&gt;
+ &lt;Description&gt;<strong>engineDescription</strong>&lt;/Description&gt;
+ &lt;InputEncoding&gt;<strong>inputEncoding</strong>&lt;/InputEncoding&gt;
+ &lt;Image width="16" height="16" type="image/x-icon"&gt;data:image/x-icon;base64,<strong>imageData</strong>&lt;/Image&gt;
+ &lt;Url type="text/html" method="<strong>method</strong>" template="<strong>searchURL</strong>"&gt;
+ &lt;Param name="<strong>paramName1</strong>" value="<strong>paramValue1</strong>"/&gt;
+ ...
+ &lt;Param name="<strong>paramNameN</strong>" value="<strong>paramValueN</strong>"/&gt;
+ &lt;/Url&gt;
+ &lt;Url type="application/x-suggestions+json" template="<strong>suggestionURL</strong>"/&gt;
+ &lt;moz:SearchForm&gt;<strong>searchFormURL</strong>&lt;/moz:SearchForm&gt;
+&lt;/OpenSearchDescription&gt;</pre>
+
+<dl>
+ <dt><strong>ShortName</strong></dt>
+ <dd>对搜索引擎的简称</dd>
+ <dd><strong>限制:</strong> 名称仅能包含16个字符以下的纯文本. 名称不能包含HTML标志或其他标志.</dd>
+</dl>
+
+<dl>
+ <dt><strong>Description</strong></dt>
+ <dd>对于搜索引擎的简单描述</dd>
+ <dd><strong>限制:</strong> 描述仅能包含少于1024个字符的纯文本.  名称不能包含HTML标志或其他标志.</dd>
+</dl>
+
+<dl>
+ <dt><strong>InputEncoding</strong></dt>
+ <dd>向搜索引擎所输内容的字符编码.例如: <code>&lt;InputEncoding&gt;UTF-8&lt;/InputEncoding&gt;</code>.</dd>
+</dl>
+
+<dl>
+ <dt><strong>Image</strong></dt>
+ <dd>使用指向一个图标的URL来代表这个搜索引擎. 可能的话, 应提供16x16大小的"image/x-icon"类型的图像以及一个64x64大小的 "image/jpeg" 或 "image/png"类型的图像. 链接也可以使用 <a class="external" href="http://en.wikipedia.org/wiki/Data:_URI_scheme">data: URI scheme</a>.  <a class="external" href="http://software.hixie.ch/utilities/cgi/data/data">The data: URI kitchen</a>在这能找到一个能有效地帮助你构建写在此处的数据的工具.
+ <pre class="eval">&lt;Image height="16" width="16" type="image/x-icon"&gt;<a class="external" href="http://example.com/favicon.ico" rel="freelink">http://example.com/favicon.ico</a>&lt;/Image&gt;
+  OR
+&lt;Image height="16" width="16"&gt;data:image/x-icon;base64,AAABAAEAEBAAA ... DAAA=&lt;/Image&gt;
+</pre>
+ Firefox以base64编码的data: URI (搜索插件被保存在 profile中的 "searchplugins" 文件夹) 缓存此图标. 当这完成时, http: URIs 被改变为 data: URIs.</dd>
+</dl>
+
+<dl>
+ <dt><strong>Url</strong></dt>
+ <dd>描述用来实现搜索请求的一个或多个URL.  <code>method</code> 属性决定使用 <code>GET</code> 还是 <code>POST</code>请求来获取返回的数据. <code>template</code> 属性指定实现搜索请求的 URL.</dd>
+ <dd>
+ <div class="note"><strong>注意:</strong> IE7 不支持 <code>POST</code> 请求.</div>
+ </dd>
+</dl>
+
+<dl>
+ <dd>这是两种firefox支持的URL类型:</dd>
+</dl>
+
+<ul>
+ <li><code>type="text/html"</code> 用来指定进行搜索查询的URL.</li>
+ <li><code>type="application/x-suggestions+json"</code> 用来指定获取搜索建议(search suggestions)的URL.</li>
+</ul>
+
+<dl>
+ <dd>这两种URL任何一种你都能使用 <code>{searchTerms}</code>来替换用户在搜索栏中输入的搜索内容. 其他支持的动态搜索参数可见 <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/1.1/Draft_3#OpenSearch_1.1_parameters">OpenSearch 1.1 parameters</a>.</dd>
+</dl>
+
+<dl>
+ <dd>对使用搜索建议查询来说,  URL template用来获取JSON格式的建议列表. 若需要知道关于如何在服务器上实现搜索建议支持, 请见 <a href="/en/Supporting_search_suggestions_in_search_plugins" title="en/Supporting_search_suggestions_in_search_plugins">Supporting search suggestions in search plugins</a>.</dd>
+</dl>
+
+<p><img alt="Image:SearchSuggestionSample.png" class="internal" src="/@api/deki/files/358/=SearchSuggestionSample.png"></p>
+
+<dl>
+ <dt><strong>Param</strong></dt>
+ <dd>这个参数用来包括那些需要和搜索查询一起被传递的作为键值对的参数.<code> 你能使用{searchTerms}</code>来指代用户输入的搜索条目.</dd>
+ <dd>
+ <div class="note"><strong>注意:</strong> IE7不支持此元素.</div>
+ </dd>
+</dl>
+
+<dl>
+ <dt><strong>SearchForm</strong></dt>
+ <dd>跳往搜索页的 URL. 这使得Firefox能让用户直接浏览目的网站.</dd>
+ <dd>
+ <div class="note"><strong>注意:</strong> 这个元素是firefox限定的, 并不是 OpenSearch 的一部分, 我们在例子中使用 "<code>moz:</code>" XML命名前缀来确保其它的不支持此元素的用户代理能安全地忽略此元素.</div>
+ </dd>
+</dl>
+
+<h2 id="自动搜寻搜索插件">自动搜寻搜索插件</h2>
+
+<p>提供搜索插件的网站能宣传自己以使firefox使用者能容易地下载并安装此插件.</p>
+
+<p>要支持自动搜寻 你仅需在 你网页的<code>&lt;head&gt;</code> 中加上一条:</p>
+
+<pre class="eval">&lt;link rel="search" type="application/opensearchdescription+xml" title="<em>searchTitle</em>" href="<em>pluginURL</em>"&gt;
+</pre>
+
+<p>斜体字部分解释如下:</p>
+
+<dl>
+ <dt><strong>searchTitle</strong></dt>
+ <dd>搜索的名称, 如 "Search MDC" or "Yahoo! Search". 这个值应该与你在插件文件中的ShortName相一致.</dd>
+</dl>
+
+<dl>
+ <dt><strong>pluginURL</strong></dt>
+ <dd>指向 XML搜索插件的URL, 能让浏览者下载插件.</dd>
+</dl>
+
+<p>如果你的网站提供多个插件, 你能为他们每一个都支持自动搜寻功能. 例如:</p>
+
+<pre class="eval">&lt;link rel="search" type="application/opensearchdescription+xml" title="MySite: By Author" href="<a class="external" href="http://www.mysite.com/mysiteauthor.xml" rel="freelink">http://www.mysite.com/mysiteauthor.xml</a>"&gt;
+&lt;link rel="search" type="application/opensearchdescription+xml" title="MySite: By Title" href="<a class="external" href="http://www.mysite.com/mysitetitle.xml" rel="freelink">http://www.mysite.com/mysitetitle.xml</a>"&gt;
+</pre>
+
+<p>这样,你的网站提供的插件就能同时以作者和名称分别作为搜索条目而被搜索.</p>
+
+<h2 id="为_OpenSearch_插件支持自动更新">为 OpenSearch 插件支持自动更新</h2>
+
+<p>{{ fx_minversion_note("3.5", "This section covers a feature introduced in Firefox 3.5.") }}</p>
+
+<p>从Firefox 3.5开始, OpenSearch 插件能够自动更新.  要支持这个, 需要包括一个额外的 "<code>application/opensearchdescription+xml</code>"类型<code>Url</code> 元素.  <code>rel</code>属性需要设为 "<code>self</code>" , template 属性需要是指向能自动更新的OpenSearch文档的 URL.</p>
+
+<p>例如:</p>
+
+<pre>&lt;Url type="application/opensearchdescription+xml"
+     rel="self"
+     template="http://www.foo.com/mysearchdescription.xml" /&gt;
+</pre>
+
+<div class="note"><strong>注意:</strong>  <a class="external" href="http://addons.mozilla.org" title="http://addons.mozilla.org/">addons.mozilla.org</a> (AMO) 不支持 OpenSearch 插件的自动更新. 如果你想将你的插件发布在 AMO上, 你不应该使用自动更新.</div>
+
+<h2 id="排错指南">排错指南</h2>
+
+<p>如果你的搜索插件有错误, 当在firefox2中添加插件时会出错. 然而,错误信息可能并不是完全有所帮助的, 因此接下来的建议能帮你发现问题.</p>
+
+<ul>
+ <li>你的服务器应当运行使用MIME类型为<code>application/opensearchdescription+xml的</code> OpenSearch 插件.</li>
+ <li>确保你的搜索插件正确地格式化了. 你能通过直接将插件加载入firefox来检查.  template URL 中的&amp;符号需要使用 &amp;amp代替;标签需要以斜杠或是相匹配的结束标志结束。</li>
+ <li><code>xmlns</code>属性是很重要的, 没有了他你会得到 "Firefox could not download the search plugin from: (URL)"错误信息.</li>
+ <li>注意你必须包含一个 <code>text/html</code> URL — 仅包含 Atom 或 <a href="/en/RSS" title="en/RSS">RSS</a> URL 类型 (有效但firefox不支持)的插件将产生  "could not download the search plugin"错误.</li>
+ <li>远程获取的收藏夹图标大小不能超过10KB (见 {{ Bug(361923) }}).</li>
+</ul>
+
+<p>另外, 搜索插件服务提供了日志机制,这对于插件开发者来说可能能起到一定作用 . 使用 <em>about:config</em> 设定 '<code>browser.search.log</code>' 为 <code>true</code>. 插件被加载后日志信息将显示在火狐的 <a href="/en/Error_Console" title="en/Error_Console">Error Console</a> 中(Tools-&gt;Error Console).</p>
+
+<h2 id="参考资料">参考资料</h2>
+
+<ul>
+ <li><a class="external" href="http://opensearch.org/">OpenSearch Documentation</a>, <a class="external" href="http://www.opensearch.org/Specifications/OpenSearch/Extensions/Parameter/1.0">OpenSearch Documentation about the Url and Param element</a></li>
+ <li>Technorati.com has a <a class="external" href="http://technorati.com/osd.xml">working osd.xml</a></li>
+ <li>More on Autodiscovery difficulties at bugzilla {{ Bug(340208) }}</li>
+ <li><a class="external" href="http://en.wikipedia.org/wiki/Data:_URI_scheme"><code>data:</code> URI scheme</a></li>
+ <li><a class="external" href="http://www.searchplugins.net">searchplugins.net</a> - create OpenSearch plugins for use with Firefox 2. <a class="external" href="http://www.searchplugins.net/pluginlist.aspx">List of generated search plugins</a></li>
+ <li><a class="external" href="http://keijisaito.info/ready2search/e/">Ready2Search</a> - create OpenSearch plugins. <a class="external" href="http://keijisaito.info/arc/search/en_make_plugin.htm">Customized Search through Ready2Search</a></li>
+</ul>
+
+<p>{{ languages( { "es": "es/Creación_de_plugins_OpenSearch_para_Firefox", "de": "de/OpenSearch_Plugin_für_Firefox_erstellen", "ca": "ca/Creació_de_connectors_OpenSearch_per_al_Firefox", "fr": "fr/Création_de_plugins_OpenSearch_pour_Firefox", "ja": "ja/Creating_OpenSearch_plugins_for_Firefox", "pl": "pl/Tworzenie_wtyczek_OpenSearch_dla_Firefoksa", "pt": "pt/Criando_plugins_OpenSearch_para_o_Firefox" } ) }}</p>
diff --git a/files/zh-cn/mozilla/add-ons/extension_frequently_asked_questions_move/index.html b/files/zh-cn/mozilla/add-ons/extension_frequently_asked_questions_move/index.html
new file mode 100644
index 0000000000..6b9e091642
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/extension_frequently_asked_questions_move/index.html
@@ -0,0 +1,35 @@
+---
+title: 扩展的常见问题解答
+slug: Mozilla/Add-ons/Extension_Frequently_Asked_Questions_move
+translation_of: Archive/Mozilla/Extension_Frequently_Asked_Questions
+---
+<p>这里是关于<a class="internal" href="/cn/%E6%89%A9%E5%B1%95" title="cn/扩展">扩展</a>开发中最常见问题的解答集锦。其中的绝大多数是关于 FireFox 的,但是大部分能够方便的移植到 SeaMonkey,Thunderbird 或其它 Mozilla 应用上。</p>
+<p>如果你还不知道怎么开始,可以先看看我们的教程:<a class="internal" href="/cn/%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E6%89%A9%E5%B1%95" title="Cn/构建一个扩展">构建一个扩展</a>或者 <a class="external" href="http://kb.mozillazine.org/Getting_started_with_extension_development" title="http://kb.mozillazine.org/Getting_started_with_extension_development">MozillaZine 上的新手教程</a>。然后用<a class="external" href="http://ted.mielczarek.org/code/mozilla/extensionwiz/" title="http://ted.mielczarek.org/code/mozilla/extensionwiz/">扩展向导</a>创建一个供开始用的简单扩展。</p>
+<p>不要忘记先<a class="internal" href="/%E8%AE%BE%E7%BD%AE%E6%89%A9%E5%B1%95%E7%9A%84%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83" title="设置扩展的开发环境">设置好扩展的开发环境</a>。</p>
+<h2 id="调试">调试</h2>
+<p>调试之前先<a class="internal" href="/%E8%AE%BE%E7%BD%AE%E6%89%A9%E5%B1%95%E7%9A%84%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83" title="设置扩展的开发环境">设置扩展的开发环境</a>。</p>
+<p>如果调试的代码很复杂,可能会用到 <a class="internal" href="/cn/venkman" title="cn/Venkman">Venkman</a> JavaScript 调试器。在用 Venkman 调试扩展代码之前需要把 "Debug -&gt; Exclude Browser Files" 选项勾掉。</p>
+<h3 id="怎样记录代码中的错误?">怎样记录代码中的错误?</h3>
+<p>将<a class="internal" href="/%E8%AE%BE%E7%BD%AE%E6%89%A9%E5%B1%95%E7%9A%84%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83" title="设置扩展的开发环境"><strong>javascript.options.showInConsole</strong> 设为 <strong>true</strong></a>,这样错误就会被记录在<a class="internal" href="/cn/%E9%94%99%E8%AF%AF%E6%8E%A7%E5%88%B6%E5%8F%B0" title="cn/错误控制台">错误控制台</a>中,使得 bug 容易追踪些。</p>
+<h3 id="怎样显示扩展当前状态?">怎样显示扩展当前状态?</h3>
+<p>要想显示变量值,调试消息等,可以使用 alert(),dump() ,Components.utils.reportError() 或者控制台服务。当然也可以用 Venkman 调试器。</p>
+<h3 id="为什么我的脚本不能正确运行?">为什么我的脚本不能正确运行?</h3>
+<p>如果你的脚本不能如预期运行,第一个要检查的是错误控制台(参见#)。</p>
+<p>访问尚未加载完毕的 DOM 也常常是错误的来源。这种错误通常是因为初始化代码被放在程序顶层(即所有函数之外)。通过监听 <span style="font-family: Courier New;">load</span> 事件延期执行初始化代码可以解决这个问题(<span style="font-family: Courier New;">load</span> 事件表示窗口已经加载完毕):</p>
+<pre class="eval">function exampleBrowserStartup(event)
+{
+ // 初始化代码
+}
+window.addEventListener("load", exampleBrowserStartup, false);
+</pre>
+<p> </p>
+<h3 id="不能访问网页的文档(document)对象">不能访问网页的文档(document)对象</h3>
+<p>要从 browser.xul 这个 overlay 中访问当前网页,应当使用 <span style="font-family: Courier New;">content.document </span>而不是 <span style="font-family: Courier New;">document。这是因为 document 表示浏览器窗口自身。更多信息参考 <a class="internal" href="/en/Working_with_windows_in_chrome_code" title="En/Working with windows in chrome code">Working with windows in chrome code</a>。</span></p>
+<h3 id="无法在扩展中使用_XMLHttpRequest">无法在扩展中使用 XMLHttpRequest</h3>
+<p>使用 XMLHttpRequest 发送接收信息时,一般都需要做跨域(crosss domain)操作。 一般来说跨域很麻烦,但因为在 chrome 窗口内发起请求时,是在安全区域内的,所以请求会被默许。</p>
+<p>You need to make sure that you are initializing the cross domain XMLHttpRequest from JavaScript code that is referencing a XUL window. If you try and execute the request in relation to the browser content document, as opposed to the "document" of the XUL window, you will receive a Permission Denied error.</p>
+<h3 id="XML_文件是规范的,但是却出现_XML_解析错误!">XML 文件是规范的,但是却出现 XML 解析错误!</h3>
+<h3 id="示例代码">示例代码</h3>
+<h3 id="得到更多帮助">得到更多帮助</h3>
+<p> </p>
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/extension_packaging/index.html b/files/zh-cn/mozilla/add-ons/extension_packaging/index.html
new file mode 100644
index 0000000000..8057385c7c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/extension_packaging/index.html
@@ -0,0 +1,38 @@
+---
+title: 扩展打包
+slug: Mozilla/Add-ons/Extension_Packaging
+tags:
+ - Extensions
+ - Toolkit API
+translation_of: Archive/Add-ons/Extension_Packaging
+---
+<p> </p>
+<p>扩展为一种<a href="cn/Bundles">可安装包</a>的形式,它可以由使用者下载并安装,或者是由外部程序或应用程序提供的预安装包。扩展使用<a href="cn/Bundles">目录结构</a>,此结构提供有chrome,components,和其他文件以扩展XUL程序的功能。</p>
+<p>每个扩展必须提供一个<a href="cn/Install.rdf">install.rdf</a>文件,包含关于扩展的元数据,例如唯一的ID,版本,作者,和兼容性信息。</p>
+<p>扩展文件和install.rdf准备好之后,有几种方法准备扩展以便安装:将扩展目录ZIP打包为用户可安装的<a href="cn/XPI">XPI</a>(xpinstall)文件,直接将扩展解开到用户程序或设置目录中,或将扩展注册到Windows注册表中。</p>
+<h3 id=".E5.88.B6.E4.BD.9C.E6.89.A9.E5.B1.95XPI" name=".E5.88.B6.E4.BD.9C.E6.89.A9.E5.B1.95XPI">制作扩展XPI</h3>
+<p>一个<a href="cn/XPI">XPI</a> (XPInstall) 文件就是一个简单的ZIP文件,包括了扩展文件,<a href="cn/Install.rdf">install.rdf</a>文件在ZIP的根目录中。使用者可以从网站上下载或者从本地安装XPI文件,将其打开或拖拽到扩展管理窗口。</p>
+<p>XPI文件的MIME类型被Firefox识别为
+ <i>
+ application/x-xpinstall</i>
+ ,因为大多数HTTP服务器不能够默认设置为将.xpi返回MIME类型。在Apache HTTP服务器上,可以在设置文件或.htaccess中增加以下命令来实现:</p>
+<pre class="eval">AddType application/x-xpinstall .xpi
+</pre>
+<h3 id=".E7.9B.B4.E6.8E.A5.E5.AE.89.E8.A3.85.E6.89.A9.E5.B1.95.E6.96.87.E4.BB.B6" name=".E7.9B.B4.E6.8E.A5.E5.AE.89.E8.A3.85.E6.89.A9.E5.B1.95.E6.96.87.E4.BB.B6">直接安装扩展文件</h3>
+<p>如果你知道程序的位置(例如,如果你作为应用程序安装者的角色来安装扩展),你可以直接将扩展文件安装到&lt;appdir&gt;/extensions/&lt;extensionID&gt;中。在下次程序启动的时候扩展管理器会自动找到此扩展。</p>
+<p>当使用此方法的时候你必须核实以确保系统允许扩展目录和文件正确设置。否则,扩展管理器在此扩展下不能够正确运行,或者扩展本身不能正确工作。</p>
+<h3 id=".E4.BD.BF.E7.94.A8Windows.E6.B3.A8.E5.86.8C.E8.A1.A8.E5.B7.A5.E5.85.B7.E6.B3.A8.E5.86.8C.E6.89.A9.E5.B1.95.E6.89.80.E5.9C.A8.E7.9B.AE.E5.BD.95" name=".E4.BD.BF.E7.94.A8Windows.E6.B3.A8.E5.86.8C.E8.A1.A8.E5.B7.A5.E5.85.B7.E6.B3.A8.E5.86.8C.E6.89.A9.E5.B1.95.E6.89.80.E5.9C.A8.E7.9B.AE.E5.BD.95">使用Windows注册表工具注册扩展所在目录</h3>
+<p>外部安装程序(例如Java虚拟机)也许希望将应用程序整合点作为扩展安装,即便是应用程序还没有安装。这可以在Windows中<a href="cn/Adding_Extensions_using_the_Windows_Registry">使用注册表</a>来完成。</p>
+<h3 id=".E5.A4.9A.E6.9D.A1.E7.9B.AE.E6.89.A9.E5.B1.95_XPIs" name=".E5.A4.9A.E6.9D.A1.E7.9B.AE.E6.89.A9.E5.B1.95_XPIs">多条目扩展 XPIs</h3>
+<p>在有些情况下也许希望用单独的XPI文件安装多个扩展/主题。一种特殊的扩展XPI称为<a href="cn/Multiple_Item_Packaging">多条目包</a>,用来解释如何创建此类型的扩展包。(需要Firefox 1.5/XULRunner 1.8。)</p>
+<h3 id="Toolkit_API.E7.9A.84.E5.AE.98.E6.96.B9.E5.8F.82.E8.80.83" name="Toolkit_API.E7.9A.84.E5.AE.98.E6.96.B9.E5.8F.82.E8.80.83"><a href="cn/Toolkit_API">Toolkit API</a>的官方参考</h3>
+<p>
+ </p><ul>
+ <li><a href="/en/Bundles" title="en/Bundles">Structure of an Installable Bundle</a>: describes the common structure of installable bundles, including extensions, themes, and XULRunner applications</li>
+ <li><a href="/en/Extension_Packaging" title="en/Extension_Packaging">Extension Packaging</a>: specific information about how to package extensions</li>
+ <li><a href="/en/Theme_Packaging" title="en/Theme_Packaging">Theme Packaging</a>: specific information about how to package themes</li>
+ <li><a href="/en/Multiple_Item_Packaging" title="en/Multiple_Item_Packaging">Multiple-item Extension Packaging</a>: specific information about multiple-item extension XPIs</li>
+ <li><a href="/en/XUL_Application_Packaging" title="en/XUL_Application_Packaging">XUL Application Packaging</a>: specific information about how to package XULRunner applications</li>
+ <li><a href="/en/Chrome_Registration" title="en/Chrome_Registration">Chrome Registration</a></li>
+ <li><a href="/en-US/docs/Mozilla/Tech/XUL/Printing">Printing in XUL Apps</a></li>
+ </ul>
diff --git a/files/zh-cn/mozilla/add-ons/index.html b/files/zh-cn/mozilla/add-ons/index.html
new file mode 100644
index 0000000000..90026e701c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/index.html
@@ -0,0 +1,87 @@
+---
+title: 附加组件
+slug: Mozilla/Add-ons
+tags:
+ - Add-ons
+ - Extension
+ - Mozilla
+ - 扩展
+ - 附加组件
+translation_of: Mozilla/Add-ons
+---
+<div>{{AddonSidebar}}</div>
+
+<p>附加组件允许开发者们去扩展和修改 Firefox 的功能。开发者们能使用标准的 Web 技术「JavaScript,HTML 以及 CSS」再加上一些专用的 JavaScript APIs 来开发附加组件。除此之外,附加组件还能:</p>
+
+<ul>
+ <li>改变指定网站的外观或者内容</li>
+ <li>修改 Firefox 的用户界面</li>
+ <li>给 Firefox 加上新功能</li>
+</ul>
+
+<p>有几种附件组件类型,但最常见类型是扩展。</p>
+
+<h2 id="开发扩展">开发扩展</h2>
+
+<p>在过去,有几种工具集用于开发 Firefox 扩展,但是到 2017 年 11 月底,扩展必须使用 <a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions">WebExtensions APIs</a> 构建。其余工具集「包括 overlay add-ons、bootstrapped add-ons 和 Add-on SDK」将会同时被废弃。</p>
+
+<p>如果你在编写一个新的扩展,请使用 <a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions">WebExtensions APIs</a>。</p>
+
+<p>使用 Firefox WebExtensions APIs 编写的扩展设计为跨浏览器兼容。在大多数情况下它也能在 Chrome,Edge 和 Opera 中运行,几乎没有任何变化。它们也完全兼容多进程 Firefox。</p>
+
+<p><a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs">查看目前在火狐和其他浏览器中支持的 APIs</a>. 我们将继续设计并改进新的 API 以满足开发人员的需求。</p>
+
+<p>绝大多数的 WebExtensions APIs 对于 Firefox Android 版也是可用的。</p>
+
+<h3 id="迁移现有扩展">迁移现有扩展</h3>
+
+<p>如果你正在维护一个旧式扩展,比如 XUL overlay、bootstrapped,或者基于 Add-on SDK 的扩展,我们建议你使用 WebExtension APIs 移植它。这里有一些 <a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/Porting_a_legacy_Firefox_add-on"> MDN 中的移植教程</a>。</p>
+
+<p style="position: relative; max-width: 400px; margin-bottom: 70px;">我们在 wiki 页面收集了一些<a href="https://wiki.mozilla.org/Add-ons/developer/communication">教程</a>来支持开发者们过渡。在开始之前,请使用兼容性<a href="https://compatibility-lookup.services.mozilla.com/">检测工具</a>来查看你的附加组件是否受影响。</p>
+
+<h2 id="发布附加组件">发布附加组件</h2>
+
+<p><a href="https://addons.mozilla.org">Addons.mozilla.org</a>,俗称 「AMO」,是 Mozilla 官方的官方站点, 方便开发者发布扩展组件和用户查找。通过上传附加组件到  AMO, 你可以加入我们的用户和开发者社区,为你的附加组件找到订阅者。</p>
+
+<p>你不需要在 AMO 上发布你的附加组件,但你的附加组件必须要经过 Mozilla 签名,否则用户不能安装它。</p>
+
+<p>为你发布的附加组件添加概述,请查看<a href="https://developer.mozilla.org/zh-CN/Add-ons/Distribution">签名和部署你的附加组件</a>。</p>
+
+<h2 id="其他类型的附加组件">其他类型的附加组件</h2>
+
+<p>通常,当人们谈起附加组件时是指扩展工具,但是这里也有一些其他类型的附加组件允许用户定制 Firefox.  这些附加组件包括:</p>
+
+<ul>
+ <li><a href="https://developer.mozilla.org/Add-ons/Themes/Background">轻量主题</a> 是一种简单的方式来提供有限的 Firefox 定制;</li>
+ <li><a href="https://developer.mozilla.org/zh-CN/Add-ons/Firefox_for_Android">移动附加组件</a> 是给 Firefox 的 Android 版使用的。注意,虽然如此,我们仍打算弃用这些 API 依赖的一些技术。在将来,Firefox 的 Android 版将会在一定程度上完全支持 WebExtension APIs;</li>
+ <li><a href="https://developer.mozilla.org/zh-CN/docs/Creating_OpenSearch_plugins_for_Firefox">搜索引擎插件</a> 可以添加新的搜索引擎到浏览器的搜索栏;</li>
+ <li><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Creating_a_spell_check_dictionary_add-on">用户字典</a> 是可以进行各种语言的拼写检查的插件;</li>
+ <li><a href="https://support.mozilla.org/kb/use-firefox-interface-other-languages-language-pack">语言包</a> 让你有更多可用的语言用于Firefox的界面。</li>
+</ul>
+
+<h2 id="联系我们">联系我们</h2>
+
+<p>你可以从以下链接获得帮助,时刻关注关于附加组件的最新消息,并且给予我们反馈。</p>
+
+<h3 id="附加组件论坛">附加组件论坛</h3>
+
+<p>到 <a href="https://discourse.mozilla-community.org/c/add-ons">附加组件交流论坛</a> 讨论附加组件的任何方面并获得帮助。</p>
+
+<h3 id="邮件列表">邮件列表</h3>
+
+<p>通过 <strong>dev-addons</strong> 列表来讨论附加组件生态系统的发展,包括 WebExtensions 系统和 AMO。</p>
+
+<ul>
+ <li><a href="https://mail.mozilla.org/listinfo/dev-addons">dev-addons list info</a></li>
+ <li><a href="https://mail.mozilla.org/pipermail/dev-addons/">dev-addons archives</a></li>
+</ul>
+
+<h3 id="IRC">IRC</h3>
+
+<p>如果你更喜欢使用 IRC,你可以在以下 channel 和其他人交流:</p>
+
+<ul>
+ <li><a href="irc://irc.mozilla.org/addons">#addons</a> (附加组件生态系统的讨论)</li>
+ <li><a href="irc://irc.mozilla.org/extdev">#extdev</a> (附加组件的发展战略的讨论)</li>
+ <li><a href="irc://irc.mozilla.org/webextensions">#webextensions</a> (对WebExtensions具体的讨论)</li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/install_manifests/index.html b/files/zh-cn/mozilla/add-ons/install_manifests/index.html
new file mode 100644
index 0000000000..936ae3fb86
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/install_manifests/index.html
@@ -0,0 +1,363 @@
+---
+title: 安装清单
+slug: Mozilla/Add-ons/Install_Manifests
+tags:
+ - bug-840092
+ - bug-840092-dup
+translation_of: Archive/Add-ons/Install_Manifests
+---
+<h2 id="简介">简介</h2>
+<p>安装清单是一个附加文件,具有Add-on的XUL程序(例如火狐或者雷鸟),用这个文件来确定即将要安装的add-on的安装信息。他包含了add-on的元数据验证、创建者信息、add-on的详细介绍页面地址、版本号、如何更新、兼容性、等等。</p>
+<p>安装清单的格式是 RDF/XML.</p>
+<p>这个文件名字必须为 <code>install.rdf</code> 并且必须放在 XPI 文件的根目录。</p>
+<h2 id="结构">结构</h2>
+<p>安装清单的最基本结构如下:</p>
+<div style="overflow: hidden;">
+ <pre class="brush:xml;auto-links:false">&lt;?xml version="1.0"?&gt;
+
+&lt;RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#"&gt;
+ &lt;Description about="urn:mozilla:install-manifest"&gt;
+ &lt;!-- properties --&gt;
+ &lt;/Description&gt;
+&lt;/RDF&gt;
+</pre>
+</div>
+<p>有些属性是是必须的,有些是可选的。有些属性只是简单的字符串啥啥啥的,有些属性会很复杂。</p>
+<h2 id="必要的属性">必要的属性</h2>
+<p>你的清单必须要包含下面的这些属性,不听话的话,你的add-on是不会安装成功滴。</p>
+<h3 id="id">id</h3>
+<p>id是一个这样子的东东:</p>
+<ul>
+ <li><a href="/en-US/docs/Generating_GUIDs" title="Generating_GUIDs">GUID</a> (Firefox 1.0)</li>
+ <li>{{ Fx_minversion_inline(1.5) }}是一个这样结构的字符串:</li>
+</ul>
+<pre><code class="plain">extensionname@example.org</code></pre>
+<p>后面的这个格式更容易生成和操作。火狐1.5已经检测你的id,确保它是属于第一种格式还是其他格式,并且让那些id格式乱七八糟的add-on不会被安装。</p>
+<p>例如:</p>
+<pre class="brush:xml;auto-links:false">&lt;em:id&gt;extensionname@example.org&lt;/em:id&gt;
+
+&lt;em:id&gt;{daf44bf7-a45e-4450-979c-91cf07434c3d}&lt;/em:id&gt;</pre>
+<h3 id="版本">版本</h3>
+<p>一个标志当前add-on版本的字符串。</p>
+<p>对于火狐/雷鸟1.0来说,这个格式必须满足这里所说的要求: <a href="/en-US/docs/Extension_Versioning,_Update_and_Compatibility" title="Extension_Versioning,_Update_and_Compatibility">Extension Versioning, Update and Compatibility</a>. 对于火狐/雷鸟1.5, 看这里:<a href="/en-US/docs/Toolkit_version_format" title="Toolkit_version_format">Toolkit version format</a>.</p>
+<p>示例:</p>
+<pre class="brush:xml">&lt;em:version&gt;2.0&lt;/em:version&gt;
+
+&lt;em:version&gt;1.0.2&lt;/em:version&gt;
+
+&lt;em:version&gt;0.4.1.2005090112&lt;/em:version&gt;</pre>
+<p><strong>Firefox 1.5 / XULRunner 1.8</strong> - add-ons that do not use a valid version format will not be installed. The version format is different from, although backwards-compatible with, 1.0's.</p>
+<p><strong>For addons hosted on addons.mozilla.org</strong> - Mozilla's update website may repackage your add-on and correct or reject malformed version strings.</p>
+<h3 id="类型">类型</h3>
+<p>一个整数代表add-on的类型</p>
+<table>
+ <tbody>
+ <tr>
+ <td>2</td>
+ <td>扩展</td>
+ </tr>
+ <tr>
+ <td>4</td>
+ <td>主题</td>
+ </tr>
+ <tr>
+ <td>8</td>
+ <td>地区(译者注:多语言)</td>
+ </tr>
+ <tr>
+ <td>32</td>
+ <td><a href="/en-US/docs/Multiple_Item_Packaging" title="Multiple_Item_Packaging">多个物品包</a></td>
+ </tr>
+ <tr>
+ <td>64</td>
+ <td>拼写检测字典</td>
+ </tr>
+ </tbody>
+</table>
+<p>例如:</p>
+<pre class="brush:xml">&lt;em:type&gt;2&lt;/em:type&gt;</pre>
+<p>{{ Fx_minversion_inline(1.5) }} This property was added for Firefox 1.5, and is only required for add-on types other than Extensions and Themes.</p>
+<p>{{ Fx_minversion_inline(3) }} Firefox 2 and previous supported a value of 16 to represent plug-ins. In Firefox 3 this has been removed.</p>
+<h3 id="targetApplication">targetApplication</h3>
+<p>An object specifying an application targeted by this add-on. This means that the add-on will work with the application identified by the id property (<code>&lt;em:id&gt;</code>) specified (for a comprehensive list of application IDs and valid min/maxVersions for them see <a class="link-https" href="https://addons.mozilla.org/en-US/firefox/pages/appversions">Valid application versions for add-on developers</a>), from the minimum version (<code>&lt;em:minVersion&gt;</code>) up to and including the maximum version (<code>&lt;em:maxVersion&gt;</code>). These version strings are formatted in the same fashion as the <a href="#version"><code>version</code> property</a> and will be compared to the application version; this allows the extension author to specify which versions of Firefox an extension has been tested with.</p>
+<p><code>id</code>, <code>minVersion</code>, and <code>maxVersion</code> are all required.</p>
+<div class="note">
+ Extensions compatible with Firefox 3.5 should specify a <code>maxVersion</code> of<code> 3.5.*</code>, so that they are automatically compatible with security and stability updates. For Firefox 3.0, a <code>maxVersion</code> of<code> 3.0.*</code> should be used. Extensions compatible only with Firefox or Thunderbird 2 should specify a <code>maxVersion</code> of <code>2.0.0.*</code>.</div>
+<p>The Install Manifest must specify at least one of these objects, and may specify more if the add-on targets multiple applications that support the Add-on Manager (e.g. Firefox and Thunderbird)</p>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:targetApplication&gt;
+ &lt;Description&gt;
+ &lt;em:id&gt;{ec8030f7-c20a-464f-9b0e-13a3a9e97384}&lt;/em:id&gt; &lt;!--Firefox--&gt;
+ &lt;em:minVersion&gt;1.5&lt;/em:minVersion&gt;
+ &lt;em:maxVersion&gt;3.0.*&lt;/em:maxVersion&gt;
+ &lt;/Description&gt;
+&lt;/em:targetApplication&gt;</pre>
+<p>{{ Fx_minversion_inline(3) }} Gecko 1.9 based applications allow you to use the special <code>targetApplication </code>id <code class="plain">toolkit@mozilla.org</code> to say that the add-on is compatible with any toolkit app with a toolkit version matching the <code>minVersion</code> and <code>maxVersion</code>.</p>
+<h3 id="name">name</h3>
+<p>The name of the add-on; intended for display in the UI.</p>
+<p><strong>Examples </strong></p>
+<pre class="brush:xml">&lt;em:name&gt;My Extension&lt;/em:name&gt;</pre>
+<h2 id="Optional_Property_Reference">Optional Property Reference</h2>
+<p>You may need to supply these properties, depending on the capabilities of your add-on.</p>
+<h3 id="bootstrap">bootstrap</h3>
+<p>{{ Fx_minversion_inline(4) }} A Boolean value that tells the application whether the extension is boot-strappable. At the moment this only works for add-ons with em:type="2". The default value is <code>false</code>. For more information, see <a href="/en-US/docs/Extensions/Bootstrapped_extensions" title="Extensions/Bootstrapped extensions">Bootstrapped extensions</a>.</p>
+<h3 id="unpack">unpack</h3>
+<p>{{ Fx_minversion_inline(4) }} A true or false value that tells the application whether the extension requires its files be unpacked into a directory in order to work or whether the extension can be loaded direct from the XPI. In versions before Gecko 2.0 all extensions were unpacked, in Gecko 2.0 and later the default is to not unpack. If an extension includes the following then it must request unpacking:</p>
+<ul>
+ <li>Binary <a href="/en-US/docs/XPCOM" title="XPCOM">XPCOM</a> components</li>
+ <li><a href="/en-US/docs/Shipping_a_plugin_as_a_Toolkit_bundle" title="Shipping a plugin as a Toolkit bundle">Plugins</a></li>
+ <li><a href="/en-US/docs/Creating_MozSearch_plugins" title="Creating MozSearch plugins">Search plugins</a></li>
+ <li>DLLs loaded with <a href="/en-US/docs/Mozilla/js-ctypes" title="js-ctypes">ctypes</a></li>
+ <li>Dictionaries</li>
+ <li>Window icons</li>
+</ul>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;Description about="urn:mozilla:install-manifest"&gt;
+ &lt;em:id&gt;extension@mysite.com&lt;/em:id&gt;
+ &lt;em:unpack&gt;true&lt;/em:unpack&gt;
+ ...
+&lt;/Description&gt;</pre>
+<h3 id="localized">localized</h3>
+<p>{{ Fx_minversion_inline(3) }} Allows you to localize the add-on's name, description, contributors and other metadata. The localized description must specify at least one <code>em:locale</code> which indicates which locales to use this information for.</p>
+<p><strong>Examples</strong></p>
+<p>This declares a set of add-on metadata to be displayed when the application is running in the de-DE locale.</p>
+<pre class="brush:xml">&lt;em:localized&gt;
+ &lt;Description&gt;
+ &lt;em:locale&gt;de-DE&lt;/em:locale&gt;
+ &lt;em:name&gt;Tab Sidebar&lt;/em:name&gt;
+ &lt;em:description&gt;Zeigt in einer Sidebar Vorschaubilder der Inhalte aller offenen Tabs an.&lt;/em:description&gt;
+ &lt;/Description&gt;
+&lt;/em:localized&gt;</pre>
+<p>The following properties which are described elsewhere in this page can be included in the localized property:</p>
+<ul>
+ <li>name</li>
+ <li>description</li>
+ <li>creator</li>
+ <li>homepageURL</li>
+ <li>developer</li>
+ <li>translator</li>
+ <li>contributor</li>
+</ul>
+<p>More documentation can be found at <a href="/en-US/docs/Localizing_extension_descriptions" title="Localizing_extension_descriptions">Localizing extension descriptions</a>.</p>
+<h3 id="description">description</h3>
+<p>A short description of the add-on - intended for display in the user interface. This description should fit on one short line of text.</p>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:description&gt;Advanced foo tools.&lt;/em:description&gt;</pre>
+<h3 id="creator">creator</h3>
+<p>The name of the creator/principal developer - intended for display in the user interface.</p>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:creator&gt;John Doe&lt;/em:creator&gt;</pre>
+<p>or</p>
+<pre class="brush:xml">&lt;em:creator&gt;CoolExtension Team&lt;/em:creator&gt;</pre>
+<h3 id="developer">developer</h3>
+<p>{{ Fx_minversion_inline(2) }} The name(s) of co-developers. You may specify more than one of this value to specify multiple developers.</p>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:developer&gt;Jane Doe&lt;/em:developer&gt;
+&lt;em:developer&gt;Koos van der Merwe&lt;/em:developer&gt;
+</pre>
+<h3 id="translator">translator</h3>
+<p>{{ Fx_minversion_inline(2) }} The name(s) of translators. You may specify more than one of this value to specify multiple translators.</p>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:translator&gt;Janez Novak&lt;/em:translator&gt;
+&lt;em:translator&gt;Kari Nordmann&lt;/em:translator&gt;
+</pre>
+<h3 id="contributor">contributor</h3>
+<p>The name(s) of additional contributors. You may specify more than one of this value to specify multiple contributors.</p>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:contributor&gt;John Doe&lt;/em:contributor&gt;
+
+&lt;em:contributor&gt;John Doe&lt;/em:contributor&gt;
+&lt;em:contributor&gt;Jane Doe&lt;/em:contributor&gt;
+&lt;em:contributor&gt;Elvis Presley&lt;/em:contributor&gt;
+</pre>
+<h3 id="homepageURL">homepageURL</h3>
+<p>A link to the add-on's home page - intended for display in the user interface.</p>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml;auto-links:false">&lt;em:homepageURL&gt;http://www.foo.com/&lt;/em:homepageURL&gt;
+</pre>
+<h3 id="updateURL">updateURL</h3>
+<p>A link to a custom Update Manifest file that specifies available updates to the add-on. The format is described below. If enabled, the add-on manager periodically checks with this Manifest file to determine if newer versions are available.</p>
+<div class="note">
+ <strong>Note:</strong> It is strongly recommended that the <code>updateURL</code> be an HTTPS (secure) link. Non-secure update URLs can be hijacked by a malicious <code>update.rdf</code> file, enabling malware to infiltrate the user's computer. <strong>Alternatively, you could host your extension on </strong><a class="external" href="http://addons.mozilla.org"><strong>AMO</strong></a><strong> and leave out the <code>updateURL</code> completely.</strong> This provides secure updates automatically.</div>
+<p>{{ Fx_minversion_inline(3) }} For security reasons, Gecko 1.9 applications <strong>require</strong> that if you specify an <code>updateURL</code>, it must be an https URL, or you must include an <code><a href="#updateKey">updateKey</a></code>.</p>
+<p>Your server must send this file as <code>text/rdf</code>, <code>text/xml</code> or <code>application/xml+rdf</code> or the update checker may not work.</p>
+<p>The addon manager will substitute the following values into this URL in case you wish to generate the response RDF dynamically, such as using PHP or CGI:</p>
+<table>
+ <tbody>
+ <tr>
+ <td><code>%REQ_VERSION%</code></td>
+ <td>The version of the request. Currently 1</td>
+ </tr>
+ <tr>
+ <td><code>%ITEM_ID%</code></td>
+ <td>The <code>id</code> of the addon being updated</td>
+ </tr>
+ <tr>
+ <td><code>%ITEM_VERSION%</code></td>
+ <td>The <code>version</code> of the addon being updated</td>
+ </tr>
+ <tr>
+ <td><code>%ITEM_MAXAPPVERSION%</code></td>
+ <td>The <code>maxVersion</code> of the <code>targetApplication</code> object corresponding to the current application for the addon being updated.</td>
+ </tr>
+ <tr>
+ <td><code>%ITEM_STATUS%</code></td>
+ <td>{{ Fx_minversion_inline(2) }} Comma separated list of the add-ons operating status in the application. Contains at the least either <code>userEnabled</code> or <code>userDisabled</code> plus any number of <code>incompatible</code>, <code>blockslisted</code> or <code>needsDependencies</code>.</td>
+ </tr>
+ <tr>
+ <td><code>%APP_ID%</code></td>
+ <td>The <code>id</code> of the current application</td>
+ </tr>
+ <tr>
+ <td><code>%APP_VERSION%</code></td>
+ <td>The <code>version</code> of the application to check for updates for</td>
+ </tr>
+ <tr>
+ <td><code>%CURRENT_APP_VERSION%</code></td>
+ <td>{{ Fx_minversion_inline(3.5) }} The <code>version</code> of the current application</td>
+ </tr>
+ <tr>
+ <td><code>%APP_OS%</code></td>
+ <td>{{ Fx_minversion_inline(1.5) }} The value of <code><a href="/en-US/docs/OS_TARGET" title="OS_TARGET">OS_TARGET</a></code> from the Firefox build system, identifying the operating system being used.</td>
+ </tr>
+ <tr>
+ <td><code>%APP_ABI%</code></td>
+ <td>{{ Fx_minversion_inline(1.5) }} The value of the <code><a href="/en-US/docs/XPCOM_ABI" title="XPCOM_ABI">TARGET_XPCOM_ABI</a></code> value from the Firefox build system, identifying the compiler/architecture combination used to compile the current application.</td>
+ </tr>
+ <tr>
+ <td><code>%APP_LOCALE%</code></td>
+ <td>{{ Fx_minversion_inline(3) }} The current application's locale.</td>
+ </tr>
+ <tr>
+ <td><code>%UPDATE_TYPE%</code></td>
+ <td>{{ Fx_minversion_inline(4) }} <code>UPDATE_TYPE_COMPATIBILITY(32)</code>, <code>UPDATE_TYPE_NEWVERSION(64)</code></td>
+ </tr>
+ <tr>
+ <td><code>%COMPATIBILITY_MODE%</code></td>
+ <td>{{ Fx_minversion_inline(10) }} related to <a href="/en-US/docs/Firefox/Updating_add-ons_for_Firefox_10#Compatible_by_default" title="https://developer.mozilla.org/en-US/docs/Firefox/Updating_add-ons_for_Firefox_10#Compatible_by_default">default to compatible</a>, values could be <code>normal</code>, <code>ignore</code> or <code>strict</code>.</td>
+ </tr>
+ </tbody>
+</table>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml;auto-links:false">&lt;em:updateURL&gt;http://www.foo.com/update.cgi?id=%ITEM_ID%&amp;amp;version=%ITEM_VERSION%&lt;/em:updateURL&gt;
+&lt;em:updateURL&gt;http://www.foo.com/extension/windows.rdf&lt;/em:updateURL&gt;
+</pre>
+<p><strong>For add-ons hosted on addons.mozilla.org:</strong> You may not specify an <code>updateURL</code> property. By default, Mozilla applications using the Add-on Manager (such as Firefox and Thunderbird) will send update requests to <code>addons.mozilla.org</code> using the default web service. Every time you upload a new version of your add-on or change its compatibility parameters through the author interface, your update manifest will be generated automatically. Add-ons currently marked as <a class="link-https" href="https://addons.mozilla.org/firefox/pages/experimentalAddons">experimental</a> will not be updated due to security concerns.</p>
+<p><strong>Format of the Update Manifest:</strong> The Update Manifest is a RDF/XML datasource. For examples of an update manifest, see <a href="/en-US/docs/Extension_Versioning,_Update_and_Compatibility#Update_RDF_Format" title="Extension_Versioning,_Update_and_Compatibility#Update_RDF_Format">Extension Versioning, Update and Compatibility</a> and <a href="/en-US/docs/Enabling_Extension_Updates_(external)" title="Enabling_Extension_Updates_(external)">Enabling Extension Updates (external)</a>.</p>
+<h3 id="updateKey">updateKey</h3>
+<div>
+ {{ Gecko_minversion_header(1.9) }} {{ Fx_minversion_header(3) }}</div>
+<p>To ensure the security of update rdf data that is retrieved over plain http you must use a digital signature to verify the contents of the data. In order to do so you must include the public part of the cryptographic key in an updateKey entry in the install.rdf of the add-on. This can be generated using the <a href="/en-US/docs/McCoy" title="McCoy">McCoy</a> tool. Any line breaks and whitespace as part of this entry are ignored.</p>
+<pre class="brush:xml">&lt;em:updateKey&gt;MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK426erD/H3XtsjvaB5+PJqbhj
+ Zc9EDI5OCJS8R3FIObJ9ZHJK1TXeaE7JWqt9WUmBWTEFvwS+FI9vWu8058N9CHhD
+ NyeP6i4LuUYjTURnn7Yw/IgzyIJ2oKsYa32RuxAyteqAWqPT/J63wBixIeCxmysf
+ awB/zH4KaPiY3vnrzQIDAQAB&lt;/em:updateKey&gt;
+</pre>
+<h3 id="optionsURL">optionsURL</h3>
+<p>The <code>chrome://</code> URL of the extension's options dialog box. This is only useful to extensions. If this property is specified, when the extension is selected in the Extensions list, the Options button is enabled and will show this.</p>
+<pre class="brush:xml">&lt;em:optionsURL&gt;chrome://myext/content/options.xul&lt;/em:optionsURL&gt;</pre>
+<p>{{ gecko_minversion_note("7", "In Firefox 7 you can also simply include your options XUL as a file named <code>options.xul</code>, in the base directory of the add-on.") }}</p>
+<p>{{ h3_gecko_minversion("optionsType", 7) }}</p>
+<p>The type of user-interface used for displaying the options. Accepted values are:</p>
+<table style="">
+ <tbody>
+ <tr>
+ <td>1</td>
+ <td>Opens optionsURL in a dialog box</td>
+ </tr>
+ <tr>
+ <td>2</td>
+ <td><a href="/en-US/docs/Extensions/Inline_Options" title="Extensions/Inline Options">Options are displayed inside the Add-on Manager</a></td>
+ </tr>
+ <tr>
+ <td>3</td>
+ <td>Opens optionsURL in a new tab (if the application supports that), or a dialog box</td>
+ </tr>
+ </tbody>
+</table>
+<p>optionsType defaults to 1 if there is an optionsURL included in install.rdf or 2 if there is no optionsURL and the file <code>options.xul</code> exists in the root of the add-on.</p>
+<pre class="brush:xml">&lt;em:optionsType&gt;2&lt;/em:optionsType&gt;
+</pre>
+<h3 id="aboutURL">aboutURL</h3>
+<p>The<code> chrome://</code> URL of the extension's about dialog box. This is only useful to extensions. If this property is specified, when the extension is selected in the Extensions list, the About... link in the extension's context menu will show this dialog, rather than the default.</p>
+<div class="geckoVersionNote">
+ <p>{{ gecko_callout_heading("2.0") }}</p>
+ <p>The dialog receives the <code>Addon</code> object representing your add-on as a parameter.</p>
+</div>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:aboutURL&gt;<a class="external" rel="freelink">chrome://myext/content/about.xul</a>&lt;/em:aboutURL&gt;
+</pre>
+<h3 id="iconURL">iconURL</h3>
+<p>A <code>chrome://</code> URL to an icon to display in the add-ons list. The icon will be displayed at 32x32 in Firefox 3.6 and lower. In Firefox 4.0 and later the icon can be up to 48x48 pixels in size. If this property is not specified, a default icon is used.</p>
+<pre class="brush:xml">&lt;em:iconURL&gt;<a class="external" rel="freelink">chrome://myext/skin/icon.png</a>&lt;/em:iconURL&gt;
+</pre>
+<div class="note">
+ <strong>Note:</strong> For the above example to work you will also have to add a <code>skin package</code> line to your <code>chrome.manifest</code> file. See <a href="/en-US/docs/Chrome_Registration#skin" title="Chrome_Registration#skin">Chrome Registration#skin</a>. Alternatively you can place your icon in the directory specified in your <code>content package</code> line.</div>
+<p>{{ gecko_minversion_note("1.9.2", "Starting in Gecko 1.9.2 (Firefox 3.6), you can also simply include your icon, named <code>icon.png</code>, in the base directory of the add-on. This allows your add-on's icon to be displayed even when the add-on is disabled, or if the manifest is missing an <code>iconURL</code> entry.") }}</p>
+<p>{{ h3_gecko_minversion("icon64URL", "2.0") }}</p>
+<p>A <code>chrome://</code> URL to a 64x64 pixel icon to display in the add-on's details view . If this property is not specified, the smaller icon above will be used.</p>
+<pre class="brush:xml">&lt;em:icon64URL&gt;<a class="external" rel="freelink">chrome://myext/skin/icon64.png</a>&lt;/em:icon64URL&gt;
+</pre>
+<div class="note">
+ <strong>Note:</strong> For the above example to work you will also have to add a <code>skin package</code> line to your <code>chrome.manifest</code> file. See <a href="/en-US/docs/Chrome_Registration#skin" title="Chrome_Registration#skin">Chrome Registration#skin</a>. Alternatively you can place your icon in the directory specified in your <code>content package</code> line.</div>
+<p>{{ h3_gecko_minversion("targetPlatform", "1.8") }}</p>
+<p>A string specifying a platform that the add-on supports. It contains either the value of <code><a href="/en-US/docs/OS_TARGET" title="OS_TARGET">OS_TARGET</a></code> alone or combined with <code><a href="/en-US/docs/XPCOM_ABI" title="XPCOM_ABI">TARGET_XPCOM_ABI</a></code>, separated by an underscore (_).</p>
+<p>You can specify multiple <code>targetPlatform</code> properties per manifest. If any value matches the application's build parameters, it will be installed; if not, the user will get an appropriate error message.</p>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:targetPlatform&gt;WINNT_x86-msvc&lt;/em:targetPlatform&gt;
+
+&lt;em:targetPlatform&gt;Linux&lt;/em:targetPlatform&gt;
+
+&lt;em:targetPlatform&gt;Darwin_ppc-gcc3&lt;/em:targetPlatform&gt;
+
+&lt;em:targetPlatform&gt;SunOS_sparc-sunc&lt;/em:targetPlatform&gt;</pre>
+<p>Usually, you would use only the OS part for themes or for extensions that are not fully cross-platform. For extensions including binary (compiled) components, you should never use the OS alone, but include the <a href="/en-US/docs/XPCOM_ABI" title="XPCOM_ABI">ABI (s)</a> that you compiled the components with. If you want to include multiple versions of the components, you should also use <a href="/en-US/docs/Bundles#Platform-specific_Subdirectories" title="Bundles#Platform-specific_Subdirectories">Platform-specific Subdirectories</a>.</p>
+<p><strong>Notes</strong></p>
+<ul>
+ <li>In the same manifest file, you could even mix values with and without ABI. If a value for the application's OS is encountered that requires any specific ABI, the ABI is considered important for that OS and the application will refuse to install the add-on if it does not find a matching OS/ABI combination. This means that if all of the above examples would occur in one manifest, the add-on will install on any Linux build of the application, regardless of its ABI, but not on a Windows Cygwin build.</li>
+ <li>There may be builds of Firefox and Thunderbird which do not "know" their ABI (most likely ports to rare platforms, or non-official builds). These builds will refuse to install any addon that requires a specific ABI for their platform.</li>
+</ul>
+<p>This property was added for Firefox/Thunderbird 1.5. Previous versions of these applications will ignore the restrictions and install the add-on regardless of the platform.</p>
+<p>{{ h3_gecko_minversion("strictCompatibility", "10.0") }}</p>
+<p>A Boolean value indicating if the add-on should be enabled when the version of the application is greater than its max version. By default, the value of this property is <code>false</code> meaning that the compatibility checking will not be performed against the max version.</p>
+<pre class="brush:xml">&lt;em:strictCompatibility&gt;true&lt;/em:strictCompatibility&gt;</pre>
+<p>Usually, there is no need to restrict the compatibility: not all new releases will break your extension and, if it is hosted on AMO, you'll get notice several weeks in advance if a potential risk has been detected. Moreover, an extension being disabled, even for a short period, leads to a bad experience for the user. About the only time you should need to set this if your add-on does things that are likely to be broken by Firefox updates. You <strong>do not</strong> need to set this flag if your add-on has a binary component, since add-ons with binary components are always subject to strict compatibility checking (because binary components need to be rebuilt for every major application release anyway).</p>
+<div class="note">
+ <strong>Note:</strong> If you want to restore the old behavior of strict compatibility checking of all add-ons, regardless of the value of this setting in their manifests, you can set the <code>extensions.strictCompatibility</code> preference to <code>true</code>.</div>
+<div class="geckoVersionNote" style="">
+ <p class="note">{{ gecko_callout_heading("11.0") }}</p>
+ <p class="note">Starting in Gecko 11.0 {{ geckoRelease("11.0") }}, applications such as Firefox will assume add-ons that have not been updated in a very long time are no longer compatible by default.</p>
+</div>
+<h2 id="Obsolete_Property_Reference">Obsolete Property Reference</h2>
+<p>These properties were required in older versions of the Add-on Manager, but have been replaced with newer and better mechanisms.</p>
+<h3 id="file">file</h3>
+<p><strong>Firefox 1.0</strong> This property pointed to a chrome <code>.jar</code> file that contains chrome packages that require registration with the Chrome Registry.</p>
+<p>The <code>&lt;em:file&gt;</code> property has a complex object value. The uri of the value is <code>urn:mozilla:extension:file:jarFile.jar</code> where <code>jarFile.jar</code> is the name of the jar file that contains the chrome package's files. This could also be the name of a directory that contains the chrome package's files, un-jarred (e.g. <code>urn:mozilla:extension:file:directory</code>). In either case, the referenced chrome package file(s) must be placed in the <code>chrome</code> subdirectory of the XPI's top level.</p>
+<p>This object has a <code>package</code> property (with a path within the jar file or directory that leads to the location where the <code>contents.rdf</code> file responsible for registering that package is located), a <code>locale</code> property (ditto, but to register the locale) and a <code>skin</code> property (ditto, but to register the theme material).</p>
+<p>In extensions for Firefox 1.5, this property is no longer necessary: the <code><a href="/en-US/docs/Chrome_Registration" title="Chrome_Registration">chrome.manifest</a></code> at the top level of the XPI is used to locate chrome to register. If there is no chrome.manifest, this property is still read by the Add-on Manager and a chrome.manifest is generated from old-style contents.rdf.</p>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:file&gt;
+ &lt;Description about="urn:mozilla:extension:file:myext.jar"&gt;
+ &lt;em:package&gt;content/myext/&lt;/em:package&gt;
+ &lt;em:locale&gt;locale/en-US/myext/&lt;/em:locale&gt;
+ &lt;em:skin&gt;skin/classic/myext/&lt;em:skin&gt;
+ &lt;/Description&gt;
+&lt;/em:file&gt;
+</pre>
+<p>An Install Manifest may specify multiple <code>file</code> properties, one for each jar file or subdirectory that contains chrome to register.</p>
+<h3 id="hidden">hidden</h3>
+<p><strong>Firefox 1.0</strong><strong> - 3.5</strong> A boolean value that when <code>true</code> makes the add-on not show up in the add-ons list, provided the add-on is installed in a {{ Anch("restricted access area") }} (so it does not work for add-ons installed in the profile). This is for bundling integration hooks to larger applications where having an entry in the Extensions list does not make sense.</p>
+<div class="note">
+ <strong>Note:</strong> This property is no longer supported under Gecko 1.9.2 (Firefox 3.6) or later, to prevent extensions from being installed in such a way that the user might not be able to tell they're installed.</div>
+<p><strong>Examples</strong></p>
+<pre class="brush:xml">&lt;em:hidden&gt;true&lt;/em:hidden&gt;
+</pre>
+<h3 id="requires">requires</h3>
+<p><strong>Firefox 2.0 - 3.6.x</strong>. Other versions will ignore the restrictions and install the add-on regardless of the requirements.</p>
+<p>See <a class="link-https" href="https://groups.google.com/forum/#!topic/mozilla.dev.platform/u9QT2ZucV-c" title="https://groups.google.com/forum/#!topic/mozilla.dev.platform/u9QT2ZucV-c">Replacement for install.rdf property "requires"</a> discussion for rationale behind removing this feature and the suggested workaround.</p>
+<p><code>&lt;em:requires</code>&gt; has a similar syntax to the <code>&lt;em:targetApplication&gt;</code> tag (i.e. you must specify <code>&lt;em:id&gt;</code>, <code>&lt;em:minVersion&gt;</code>, <code>&lt;em:maxVersion&gt;</code> when using it). If the add-on specified by the <code>&lt;em:id&gt;</code> tag is not installed or has an incompatible version, the extension manager will disable your extension and show the message "Requires additional items". You can add as many <code>&lt;em:requires&gt;</code> tags as you like. Your extension will be disabled if any of the specified requirements fail. It is not possible to add dependencies that are specific to a <code>&lt;em:targetApplication&gt;</code>. See <a href="https://wiki.mozilla.org/Extension_Dependencies" title="https://wiki.mozilla.org/Extension_Dependencies">Extension Dependencies</a> for more details.</p>
+<h2 id="Glossary">Glossary</h2>
+<h2 id="restricted_access_area">restricted access area</h2>
+<p>A <em>restricted access area</em> is an install location that could be restricted on a restricted-access account, regardless of whether or not the location is restricted with the current user privileges (see {{ Source("toolkit/mozapps/extensions/public/nsIExtensionManager.idl#80", "nsIInstallLocation::restricted") }}). Currently, the <code>($APPDIR)/extensions</code> folder and the registry install location under <code>HKEY_LOCAL_MACHINE</code> (see <a href="/en-US/docs/Adding_Extensions_using_the_Windows_Registry" title="Adding_Extensions_using_the_Windows_Registry">Adding Extensions using the Windows Registry</a> for details) are restricted.</p>
+<p>The <code>($PROFILE)/extensions</code> and <code>HKEY_CURRENT_USER</code> install locations, on the other hand, are not restricted.</p>
diff --git a/files/zh-cn/mozilla/add-ons/legacy_add_ons/index.html b/files/zh-cn/mozilla/add-ons/legacy_add_ons/index.html
new file mode 100644
index 0000000000..9200ccb0f6
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/legacy_add_ons/index.html
@@ -0,0 +1,19 @@
+---
+title: 旧式附件组件
+slug: Mozilla/Add-ons/Legacy_add_ons
+translation_of: Archive/Add-ons/Legacy_add_ons
+---
+<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p>
+
+<p>本节包含附件组件开发的旧式技术文档链接,包括:</p>
+
+<ul>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/SDK">附件组件 SDK</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/Legacy_Firefox_for_Android">Firefox for Android旧式扩展</a></li>
+ <li>早期技术
+ <ul>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/Bootstrapped_extensions">Bootstrapped 扩展</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/Overlay_Extensions">Overlay 扩展</a></li>
+ </ul>
+ </li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/overlay_extensions/index.html b/files/zh-cn/mozilla/add-ons/overlay_extensions/index.html
new file mode 100644
index 0000000000..6504a2ef16
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/overlay_extensions/index.html
@@ -0,0 +1,61 @@
+---
+title: Overlay扩展
+slug: Mozilla/Add-ons/Overlay_Extensions
+tags:
+ - Add-ons
+ - Extensions
+ - Landing
+ - NeedsTranslation
+ - TopicStub
+translation_of: Archive/Add-ons/Overlay_Extensions
+---
+<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p>
+
+<p>本页面为那些基于 Gecko 的应用开发扩展插件的开发者们提供了可用的参考文献链接。</p>
+
+<ul>
+ <li>XUL 覆盖指定的接口</li>
+ <li>对应用与内容的之间交互的特定代码提供了可用的APIs, 比如 <a href="/zh-CN/docs/XUL/tabbrowser">页签浏览</a> 和<a href="/zh-CN/docs/Mozilla/JavaScript_code_modules">JavaScript模组</a>。</li>
+</ul>
+
+<p>唯一可行的方法是开发扩展在 Gecko 2.0 发布之前. 但是现在有两种可以选择的技术:免重启扩展和基于 SDK 的扩展插件. 这些特定的 JavaScript APIs 仍旧可以被这些较新的技术使用。</p>
+
+<p>Prior to Firefox 4, and the Gecko 2 engine that powers it, this was the only way to develop extensions. This methodology has largely been superseded by <a href="/en-US/docs/Extensions/Bootstrapped_extensions">restartless extensions</a>, and the <a href="/en-US/Add-ons/SDK">Add-on SDK</a>, which is built on top of them. The privileged JavaScript APIs described here can still be used in these newer types of add-ons.</p>
+
+<h2 id="XUL_学校">XUL 学校</h2>
+
+<p><a href="/zh-CN/Add-ons/Overlay_Extensions/XUL_School">XUL 学校</a> 是一个综合性的拓展开发指南,主要针对 Firefox 的扩展开发,但是绝大多数可应用于其他基于 Gecko 的应用。</p>
+
+<h2 id="更多资源">更多资源</h2>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><a href="/en-US/Mozilla/Add-ons/Setting_up_extension_development_environment">设置环境</a></dt>
+ <dd>设置扩展开发需要的应用.</dd>
+ <dt><a href="/en-US/docs/XUL">XUL</a></dt>
+ <dd>相关的指南介绍XUL 扩展的接口.</dd>
+ <dt><a href="/en-US/Mozilla/Add-ons/Code_snippets">代码片段</a></dt>
+ <dd>提供了很多的简单示例代码片段.</dd>
+ <dt><a href="/en-US/Mozilla/Add-ons/Installing_extensions">安装扩展</a></dt>
+ <dd>如何通过把扩展的文件拷贝进应用的安装目录来安装扩展.</dd>
+ <dt><a href="/en-US/Add-ons/Overlay_extensions/Firefox_addons_developer_guide">Firefox 插件的开发者指南</a></dt>
+ <dd>开发扩展的指南.</dd>
+</dl>
+</div>
+
+<div class="column-half">
+<dl>
+ <dt><a href="/en-US/docs/Mozilla/JavaScript_code_modules">JavaScript 模块代码</a></dt>
+ <dd>适用于扩展开发者的 JavaScript 模块。</dd>
+ <dt><a href="/en-US/Mozilla/Add-ons/Inline_Options">扩展偏好</a></dt>
+ <dd>如何在你的扩展出现在附加组件管理界面的时候指定偏好设置。</dd>
+ <dt><a href="/en-US/Mozilla/Add-ons/Extension_Frequently_Asked_Questions">常见问题</a></dt>
+ <dd>常见的扩展开发中的错误。</dd>
+ <dt><a href="/en-US/Mozilla/Add-ons/Extension_Packaging">扩展打包</a></dt>
+ <dd>看看扩展是如何被打包和安装的。</dd>
+ <dt><a href="/en-US/Mozilla/Add-ons/Creating_Custom_Firefox_Extensions_with_the_Mozilla_Build_System">Firefox 的二进制扩展</a></dt>
+ <dd>为 Firefox 创建二进制扩展。</dd>
+</dl>
+</div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/performance_best_practices_in_extensions/index.html b/files/zh-cn/mozilla/add-ons/performance_best_practices_in_extensions/index.html
new file mode 100644
index 0000000000..d6a6f7515b
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/performance_best_practices_in_extensions/index.html
@@ -0,0 +1,91 @@
+---
+title: 扩展中的性能最佳实践
+slug: Mozilla/Add-ons/Performance_best_practices_in_extensions
+translation_of: Archive/Add-ons/Performance_best_practices_in_extensions
+---
+<p>Firefox 的一个巨大优势就是可扩展性非常强。扩展组件几乎可以做任何事情。但这也带来了一个劣势: 扩展组件如果写的不好,将会大大的影响浏览器性能,包括 firefox 的整体体验。 本文则提供了一些最佳实践方式,他们不仅能够提升你的组件的性能和速度,也会对 firefox 带来同样的影响。</p>
+<h2 id="提升启动性能">提升启动性能</h2>
+<p>Extensions are loaded and run whenever a new browser window opens. That means every time a window opens, your extension can have an impact on how long it takes the user to see the content they're trying to view. There are several things you can do to reduce the amount of time your extension delays the appearance of the user's desired content.</p>
+<h3 id="只在需要的时候装载需要的东西">只在需要的时候装载需要的东西</h3>
+<p>Don't load things during startup that are only needed if the user clicks a button, or if a given preference is enabled when it's not. If your extension has features that only work when the user has logged into a service, don't load the resources for those features until the user actually logs in.</p>
+<h3 id="使用_JavaScript_code_modules">使用  JavaScript code modules</h3>
+<p>You can create your own <a href="/en-US/docs/Mozilla/JavaScript_code_modules/Using" title="/en-US/docs/Mozilla/JavaScript_code_modules/Using">JavaScript code modules</a> incorporating sets of features that are only needed under specific circumstances. This makes it easy to load chunks of your extension on the fly as needed, instead of loading everything all at once.</p>
+<p>This has an advantage over XPCOM modules, which are always loaded when your extension starts up.</p>
+<p>Of course, for extremely simple extensions it may not make sense to modularize your code.</p>
+<h3 id="Defer_everything_that_you_can">Defer everything that you can</h3>
+<p>Most extensions have a load event listener in the main overlay that runs their startup functions. Do as little as possible here. The browser window is blocked while your add-on's load handler runs, so the more it does, the slower Firefox will appear to the user.</p>
+<p>If there is <em>anything</em> that can be done even a fraction of a second later, you can use an {{ interface("nsITimer") }} or the {{ domxref("window.setTimeout()") }} method to schedule that work for later.  Even a short delay can have a big impact.</p>
+<h2 id="通用性能提示">通用性能提示</h2>
+<h3 id="避免产生内存泄漏">避免产生内存泄漏</h3>
+<p>Memory leaks require the garbage collector and the cycle collector to work harder, which can significantly degrade performance.</p>
+<p>Zombie compartments are a particular kind of memory leak that you can detect with minimal effort.  See the<a href="/en/Zombie_compartments" title="en/Zombie_compartments"> </a><a href="/en/Zombie_compartments" title="en/Zombie_compartments">Zombie compartments page</a>, especially the <a href="/en/Zombie_compartments#Proactive_checking_of_add-ons" title="en/Zombie_compartments#Proactive_checking_of_add-ons">Proactive checking of add-ons</a> section.</p>
+<p>See <a href="/en/Extensions/Common_causes_of_memory_leaks_in_extensions" title="en/Extensions/Common_causes_of_zombie_compartments_in_extensions">Common causes of memory leaks in extensions</a> for ways to avoid zombie compartments and other kinds of leaks.</p>
+<p>As well as looking for these specific kinds of leaks, it's worth exercising your extension's functionality and checking the contents of about:memory for any excessive memory usage.  For example, <a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=719601" title="https://bugzilla.mozilla.org/show_bug.cgi?id=719601">bug 719601</a> featured a "System Principal" JavaScript compartment containing 100s of MBs of memory, which is <em>much</em> larger than usual.</p>
+<h3 id="Use_JavaScript_Modules">Use JavaScript Modules</h3>
+<p>JavaScript modules are just like any other JavaScript, with the exception that they are singletons and Firefox can cache the compiled code for faster use the next time the browser is started. Any time your add-on loads JavaScript from an {{ HTMLElement("script") }} element you should consider using a JavaScript Module instead. For more on how JavaScript modules work, see the <a href="/en-US/docs/Mozilla/JavaScript_code_modules/Using" title="/en-US/docs/Mozilla/JavaScript_code_modules/Using">Using JavaScript Code Modules page</a>.</p>
+<h3 id="Avoid_Writing_Slow_CSS">Avoid Writing Slow CSS</h3>
+<ul>
+ <li>Read the <a href="/en/CSS/Writing_Efficient_CSS" title="en/CSS/Writing_Efficient_CSS">"writing efficient CSS"</a> guide.</li>
+ <li>Remember that any selector in your rule which might match many different nodes is a source of inefficiency during either selector matching or dynamic update processing. This is especially bad for the latter if the selector can dynamically start or stop matching. Avoid unqualified ":hover" like the plague.</li>
+</ul>
+<h3 id="Avoid_DOM_mutation_event_listeners">Avoid DOM mutation event listeners</h3>
+<p>Adding DOM mutation listeners to a document disables most DOM modification optimizations and <a class="external" href="http://groups.google.com/group/mozilla.dev.platform/browse_thread/thread/2f42f1d75bb906fb?pli=1">profoundly degrades the performance</a> of further DOM modifications to that document. Moreover, removing the listeners does not reverse the damage. For these reasons, the following events should be avoided wherever possible: <code>DOMAttrModified</code>, <code>DOMAttributeNameChanged</code>, <code>DOMCharacterDataModified</code>, <code>DOMElementNameChanged</code>, <code>DOMNodeInserted</code>, <code>DOMNodeInsertedIntoDocument</code>, <code>DOMNodeRemoved</code>, <code>DOMNodeRemovedFromDocument</code>, <code>DOMSubtreeModified</code></p>
+<p>For more on these events and their deprecation, see <a href="/en-US/docs/Web/Guide/DOM/Events/Mutation_events" title="en-US/docs/Web/Guide/DOM/Events/Mutation_events">Mutation events</a>. Use <a href="/en-US/docs/Web/API/MutationObserver" title="en-US/docs/Web/API/MutationObserver">Mutation Observers</a> instead if possible.</p>
+<h3 id="延迟加载服务_services">延迟加载服务 services</h3>
+<p>The <a href="/en/JavaScript_code_modules/XPCOMUtils.jsm#Methods" title="en/JavaScript_code_modules/XPCOMUtils.jsm#Methods">XPCOMUtils JavaScript module</a> provides two methods for lazily loading things:</p>
+<ul>
+ <li><code>defineLazyGetter()</code> defines a function on a specified object that acts as a getter which will be created the first time it's used. <a class="external" href="http://mxr.mozilla.org/mozilla-central/search?string=defineLazyGetter">See examples</a>.</li>
+ <li><code>defineLazyServiceGetter()</code> defines a function on a specified object which acts as a getter for a service. The service isn't obtained until the first time it's used. {{ LXRSearch("ident", "string", "defineLazyServiceGetter", "Look through the source") }} for examples.</li>
+</ul>
+<p>As of Firefox 4.0, many common services are already cached for you in <a href="/en/JavaScript_code_modules/Services.jsm" title="en/JavaScript_code_modules/Services.jsm">Services.jsm</a>.</p>
+<h3 id="Reduce_file_IO">Reduce file I/O</h3>
+<p>TODO: Give examples below, link to code, bugs, docs.</p>
+<ul>
+ <li>If you're targeting Firefox 3.6 and earlier, or if you're specifying <code>em:unpack</code> then use chrome JARs!</li>
+ <li>Combine CSS</li>
+ <li>Combine pref files</li>
+ <li>Combine interfaces into a single .idl to reduce xpt files</li>
+ <li>Combine toolbar icons in a single file.</li>
+</ul>
+<h3 id="Use_the_right_compression_level_for_JAR_and_XPI_files">Use the right compression level for JAR and XPI files</h3>
+<p>Reading data from compressed archives costs time. The higher the compression level of the archive, the higher also the performance cost of reading the data from it. So any JAR files in your extension should always be packed with compression level 0 (no compression) for better performance. It may seem counter-intuitive, but doing this will increase the JAR file size and actually <em>decrease</em> the XPI file size as it allows for compression between files inside the JAR to be done when compressing the XPI (essentially a poor-man's <a class="external" href="http://en.wikipedia.org/wiki/Solid_archive" title="http://en.wikipedia.org/wiki/Solid_archive">solid archive</a> effect).</p>
+<p>If your extension doesn't specify <code>em:unpack</code> then its XPI file will not be unpacked in Firefox 4 and used directly instead. This makes choosing a low compression level preferable; we recommend using compression level 1. It will increase the download size only a small amount, even compared to maximum compression.</p>
+<h3 id="使用异步_IO">使用异步 I/O</h3>
+<p>This cannot be stressed enough: never do synchronous I/O on the GUI thread.</p>
+<ul>
+ <li>Never use synchronous XMLHttpRequests (XHR). Use asynchronous requests instead and show a throbber image or message in case you need the user to wait.</li>
+ <li><a href="/en/JavaScript_code_modules/NetUtil.jsm" title="en/JavaScript_code_modules/NetUtil.jsm">NetUtils.jsm</a> provides helpers for asynchronous reading and copying of files.</li>
+ <li>Never access a SQLite database synchronously. Use the <a href="/en/Storage#Asynchronously" title="en/Storage#Asynchronously">asynchronous API</a> instead.</li>
+</ul>
+<h3 id="Unnecessary_onreadystatechange_in_XHR">Unnecessary onreadystatechange in XHR</h3>
+<p><code>addEventListener</code>(load/error) and/or xhr.onload/.onerror are usually sufficient for most uses and will only be called once, contrary to <code>onreadystatechange</code>. When using XHR in websites people tend to use <code>onreadystatechange</code> (for compatiblity reasons). Often it is enough to just load the resource or handle errors. load/error event listener are far less often called than <code>onreadystatechange</code>, i.e. only once, and you don't need to check <code>readyState</code> or figure out if it is an error or not. Only use <code>onreadystatechange</code> if you want to process the response while it is still arriving.</p>
+<h3 id="Removing_Event_Listeners">Removing Event Listeners</h3>
+<p>Remove event listener if they are not needed any more. It is better to actually remove event listener instead of just having some flag to check if the listener is active which is checked every time when an event is propagated. Abandon schemes like: <code>function onMouseOver(evt) { if (is_active) { /* doSomeThing */ } }</code> Also, remove "fire-once" listeners again:</p>
+<pre class="brush: js"> function init() {
+ var largeArray;
+ addEventListener('load', function onLoad() {
+ removeEventListener('load', onLoad, true);
+ largeArray.forEach();
+ }, true);
+</pre>
+<p>Else a lot of closure stuff might be still referenced (<code>largeArray</code> in this example). And the listener will sit idle in some internal table.</p>
+<h3 id="Populate_menus_as_needed">Populate menus as needed</h3>
+<p>Populate "context" menus (page, tabs, tools) as needed and keep computation to a minimum (UI responsiveness). There is no need to populate the context menu every time something changes. It is enough to populate it once the user actually needs it. Add a listener to the "popupshowing" event and compute there.</p>
+<h3 id="Avoid_mouse_movement_events">Avoid mouse movement events</h3>
+<p>Avoid mouse movement events (enter/over/exit) or at least keep computation to a minimum. Mouse movement events, especially the <code>mouseover</code> event, usually happen at high frequency. Best would be to only store the new information and compute "stuff" once the user actually requests it (e.g. in a <code>popupshowing</code> event). Also don't forget to remove the event listeners when no longer needed (see above).</p>
+<h3 id="Avoid_polling">Avoid polling</h3>
+<p>Use {{ interface("nsIObserverService") }} functionality instead. Everybody is free to post "custom" notifications via {{ interface("nsIObserverService") }}, but few extensions actually use this. However, a lot of other services also provide observer functionality, such as nsIPrefBranch2.</p>
+<h3 id="aPNGaGIF_inappropriate_in_a_lot_of_cases">aPNG/aGIF inappropriate in a lot of cases</h3>
+<p>Animations require a lot of time to set up, as a lot of images are decoded (the frames). Animated images may have their cached representations evicted quite often, causing the frames of your animated images to be reloaded lots of times, not just once. {{ interface("nsITree") }} / {{ XULElem("tree") }} seems to be extra special in this regard, as it doesn't seem to cache animations at all under certain circumstances.</p>
+<h3 id="base64md5sha1_implementations">base64/md5/sha1 implementations</h3>
+<p>Do not ship your own base64/md5/sha1 implementations. Regarding base64 there are the built-in <code>atob</code>/<code>btoa</code> functions that do the job just well and are available in overlay script as well as in in JavaScript modules and components. Hashes can be computed using {{ interface("nsICryptoHash") }}, which accepts either a string or an {{ interface("nsIInputStream") }}.</p>
+<h3 id="Image_sprites">Image sprites</h3>
+<p>You may combine multiple images into one (sprites). See {{ cssxref("-moz-image-region") }}. Most XUL widgets that are used to display some image (incl. {{ XULElem("button") }} and {{ XULElem("toolbarbutton") }}) allow to use {{ cssxref("list-style-image") }}. Avoid the <code>imagesrc</code>/<code>src</code> attributes to define images where possible.</p>
+<h3 id="Consider_using_Chrome_Workers">Consider using Chrome Workers</h3>
+<p>You can use a {{ domxref("ChromeWorker") }} to execute long running tasks or do data processing.</p>
+<h2 id="参考">参考</h2>
+<ul>
+ <li><a href="/en/Performance/Measuring_add-on_startup_performance" title="en/Measuring Add-on Startup Performance">Measuring Add-on Startup Performance</a></li>
+ <li><a class="external" href="http://blog.mozilla.com/addons/2010/06/14/improve-extension-startup-performance/" title="http://blog.mozilla.com/addons/2010/06/14/improve-extension-startup-performance/">How to Improve Extension Startup Performance</a></li>
+ <li><a href="/en-US/docs/Performance">General information about measuring and improving performance in Mozilla code</a></li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/plugins/index.html b/files/zh-cn/mozilla/add-ons/plugins/index.html
new file mode 100644
index 0000000000..f35791a3bf
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/plugins/index.html
@@ -0,0 +1,116 @@
+---
+title: Plugins
+slug: Mozilla/Add-ons/Plugins
+tags:
+ - Add-ons
+ - NPAPI
+ - NeedsTranslation
+ - Plugins
+ - TopicStub
+translation_of: Archive/Plugins
+---
+<div class="blockIndicator warning">
+<p><strong>Important</strong>: Since <a href="/en-US/docs/Mozilla/Firefox/Releases/52">Firefox 52</a>, all plugin support except Flash has been dropped (see <span><a href="https://www.fxsitecompat.com/en-CA/docs/2016/plug-in-support-has-been-dropped-other-than-flash/">Plug-in support has been dropped other than Flash</a> for more details</span>). Flash usage is also set to be phased out in the future.</p>
+</div>
+
+<div class="blockIndicator note">
+<p><strong>Note</strong>: Plugins are now a legacy technology. They are not available on most mobile devices. Mozilla encourages website developers to avoid using plugins wherever possible and use standard Web APIs instead. If there are plugin features which are not available in the web platform, we encourage developers to post their use cases to mozilla.dev.platform project list, so that Mozilla can prioritize web platform work to make those use cases possible.</p>
+</div>
+
+<p>For more information about plugin roadmap, see <a href="/en-US/docs/Plugins">non-archived plugin information</a>.</p>
+
+<p>Plugins are shared libraries that users can install to display content that the browser can't display natively. For example, the Adobe Reader plugin lets the user open PDF files directly inside the browser, and the QuickTime and RealPlayer plugins are used to play special format videos in a web page.</p>
+
+<p>Plugins are written using <strong>NPAPI</strong>, the cross-browser API for plugins. The main source of documentation for NPAPI is the <a href="/en/Gecko_Plugin_API_Reference" title="en/Gecko_Plugin_API_Reference">Gecko Plugin API Reference</a>. To make your plugin scriptable from web pages, use <a href="/en/Gecko_Plugin_API_Reference/Scripting_plugins" title="en/Gecko_Plugin_API_Reference/Scripting_plugins">npruntime</a>.</p>
+
+<p>Plugins can be written completely from scratch using C APIs (usually in C or C++) or they may be built on a plugin framework such as <a class="external" href="http://www.firebreath.org" title="http://www.firebreath.org/">Firebreath</a>, <a class="external" href="http://www.juce.com/" title="http://www.rawmaterialsoftware.com/juce.php">JUCE</a>, or <a class="external" href="http://doc.qt.nokia.com/solutions/4/qtbrowserplugin/developingplugins.html" title="http://doc.qt.nokia.com/solutions/4/qtbrowserplugin/developingplugins.html">QtBrowserPlugin</a>. There are also some code generation tools that may be helpful. More information about these tools can be found on the <a href="/en/Plugins/External_resources_for_plugin_creation" title="en/Plugins/External resources for plugin creation">External Resources</a> page.</p>
+
+<p>Plugins are different from <a href="/en/Extensions" title="en/Extensions">extensions</a>, which modify or enhance the functionality of the browser itself. Plugins are also different from <a href="/en/Creating_OpenSearch_plugins_for_Firefox" title="en/Creating_OpenSearch_plugins_for_Firefox">search plugins</a>, which plug additional search engines in the search bar.</p>
+
+<hr>
+<div class="topicpage-table">
+<div class="section">
+<dl>
+ <dt><a href="/en/Gecko_Plugin_API_Reference" title="en/Gecko_Plugin_API_Reference">Gecko Plugin API Reference</a> (NPAPI)</dt>
+ <dd>This reference describes the application programming interfaces for NPAPI plugins and provides information about how to use these interfaces.</dd>
+ <dt><a href="/en-US/docs/Site_Author_Guide_for_Click-To-Activate_Plugins">Site Author Guide For Click-To-Activate Plugins</a></dt>
+ <dd>These guidelines will help website authors use plugins when they are blocked by default with the Firefox click-to-activate feature.</dd>
+</dl>
+
+<dl>
+ <dt><a href="/en/Gecko_Plugin_API_Reference/Scripting_plugins" title="en/Gecko_Plugin_API_Reference/Scripting_plugins">Scripting plugins</a> (npruntime)</dt>
+ <dd>This reference describes the new cross-browser NPAPI extensions that let plugins be scriptable and also let them access the script objects in the browser.</dd>
+</dl>
+
+<dl>
+ <dt><a href="/en/Shipping_a_plugin_as_a_Toolkit_bundle" title="en/Shipping_a_plugin_as_a_Toolkit_bundle">Shipping a plugin as a Toolkit bundle</a></dt>
+ <dd>Plugins can be shipped as a Toolkit <a href="/en/Bundles" title="Bundles">bundle</a>, allowing a user to easily install, uninstall and manage their personal plugins.</dd>
+</dl>
+
+<dl>
+ <dt><a class="internal" href="/En/Supporting_private_browsing_in_plugins" title="en/Supporting private browsing in plugins">Supporting private browsing in plugins</a></dt>
+ <dd>Firefox 3.5 introduced support for private browsing; learn how to make your plugin respect the user's privacy wishes.</dd>
+ <dt><a href="/en/Plugins/Multi-Process_Plugin_Architecture" title="en/Plugins/Multi-Process Plugin Architecture">Multi-Process Plugin Architecture</a></dt>
+ <dd>How Firefox loads plugins into a separate process. Firefox 3.6.4 introduced out-of-process plugins which execute in a separate process so that a crashing plugin does not crash the browser.</dd>
+ <dt><a href="/en/Plugins/Logging" title="en/Plugins/Logging">Logging and Debugging for Multi-Process Plugins</a></dt>
+ <dd>How to create a plugin log to aid in debugging problems with multi-process plugins.</dd>
+</dl>
+</div>
+
+<div class="section">
+<dl>
+ <dt><a class="internal" href="/En/Writing_a_plugin_for_Mac_OS_X" title="en/Writing a plugin for Mac OS X">Writing a plugin for Mac OS X</a></dt>
+ <dd>Learn how to write a plugin for Mac OS X; a template Xcode project is provided.</dd>
+</dl>
+
+<dl>
+ <dt><a href="/en/Monitoring_plugins" title="en/Monitoring_plugins">Monitoring Plugins</a></dt>
+ <dd>Use an observer service notification to monitor the amount of time spent executing calls in plugins. This can be useful when trying to determine if a plug-in is consuming too many resources.</dd>
+</dl>
+
+<dl>
+ <dt><a href="/en/Scripting_Plugins/Adobe_Flash" title="en/Scripting_Plugins/Macromedia_Flash">Scripting Plugins: Macromedia Flash</a></dt>
+ <dd>This article explains how JavaScript can be used to access methods from within the Flash plugin, as well as how a feature called FSCommands can be used to access JavaScript functions from within the Flash animation.</dd>
+</dl>
+
+<dl>
+ <dt><a href="/en/Gecko_Plugin_API_Reference/Plug-in_Development_Overview" title="en/Plugins/The_First_Install_Problem">Plugins: The First Install Problem</a></dt>
+ <dd>The First Install Problem is the name given to the conditions arising when a plugin or embeddable software installs itself on a system first, before any other Gecko-based browser.</dd>
+</dl>
+
+<dl>
+ <dt><a href="/en/Plugins/Samples_and_Test_Cases" title="en/Plugins/Samples_and_Test_Cases">Plugins: Samples and Test Cases</a></dt>
+ <dd>NPAPI plugin samples and test cases.</dd>
+ <dt><a href="/en/Plugins/External_resources_for_plugin_creation" title="https://developer.mozilla.org/en/Plugins/External_resources_for_plugin_creation">External Resources for Plugin Creation</a></dt>
+ <dd>External projects, frameworks, and blog posts that may be useful.</dd>
+</dl>
+
+<dl>
+ <dt><a href="/en/XEmbed_Extension_for_Mozilla_Plugins" title="en/XEmbed_Extension_for_Mozilla_Plugins">XEmbed Extension for Mozilla Plugins</a></dt>
+ <dd>Recent versions of Mozilla on *nix-based systems include an extension for writing plugins that use XEmbed instead of using the old Xt-based main loop that most plugins have been using since the Netscape 3.x days.</dd>
+</dl>
+</div>
+</div>
+
+<hr>
+<p><span class="comment">Categories</span></p>
+
+<p><span class="comment">Interwiki Language Links</span></p>
+
+<div class="blockIndicator communitybox" dir="ltr">
+<div class="column-container">
+<h2 id="Join_the_plugin_development_community">Join the plugin development community</h2>
+
+<div class="column-half">
+<div class="communitysubhead">Choose your preferred method for joining the discussion:</div>
+
+<ul class="communitymailinglist">
+ <li><a href="https://lists.mozilla.org/listinfo/dev-tech-plugins">Mailing list</a></li>
+ <li><a href="http://groups.google.com/group/mozilla.dev.tech.plugins">Newsgroup</a></li>
+ <li><a href="http://groups.google.com/group/mozilla.dev.tech.plugins/feeds">RSS feed</a></li>
+</ul>
+</div>
+
+<div class="column-half"> </div>
+</div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/plugins/reference/index.html b/files/zh-cn/mozilla/add-ons/plugins/reference/index.html
new file mode 100644
index 0000000000..fcb2ba7232
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/plugins/reference/index.html
@@ -0,0 +1,16 @@
+---
+title: NPAPI plugin reference
+slug: Mozilla/Add-ons/Plugins/Reference
+tags:
+ - Deprecated
+ - Landing
+ - NPAPI
+ - NeedsTranslation
+ - Plugins
+ - Reference
+ - TopicStub
+translation_of: Archive/Plugins/Reference
+---
+<p>{{deprecated_header}}</p>
+<p>The articles below describe each of the APIs related to NPAPI plugins.</p>
+<p>{{LandingPageListSubpages}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/plugins/samples_and_test_cases/index.html b/files/zh-cn/mozilla/add-ons/plugins/samples_and_test_cases/index.html
new file mode 100644
index 0000000000..4d0ac34085
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/plugins/samples_and_test_cases/index.html
@@ -0,0 +1,21 @@
+---
+title: Samples and Test Cases
+slug: Mozilla/Add-ons/Plugins/Samples_and_Test_Cases
+translation_of: Archive/Plugins/Samples_and_Test_Cases
+---
+<h2 id="NPAPI_Plugin_Samples">NPAPI Plugin Samples</h2>
+<p>Collections of NPAPI plugin samples can be found in the Seamonkey source code at <a class="external" href="http://mxr.mozilla.org/seamonkey/source/modules/plugin/samples/" title="http://mxr.mozilla.org/seamonkey/source/modules/plugin/samples/">/modules/plugin/sdk/samples</a>.</p>
+<p>The samples may not build any more on all platforms. There are plans to clean up the sample plugin situation - better organization, updated build systems, get them building on all platforms. However, even if one cannot build the samples they can still be very valuable as code references.</p>
+<p>There is a <a href="/en/Compiling_The_npruntime_Sample_Plugin_in_Visual_Studio" title="en/Compiling_The_npruntime_Sample_Plugin_in_Visual_Studio">guide to compiling the npruntime sample in Visual Studio</a>.</p>
+<p>In addition to those samples, there are 2 more plugins in the tree that might be helpful.</p>
+<ul>
+ <li><a class="external" href="http://mxr.mozilla.org/seamonkey/source/modules/plugin/tools/spy/">Spy</a></li>
+ <li><a class="external" href="http://mxr.mozilla.org/seamonkey/source/modules/plugin/tools/tester/">Tester</a></li>
+</ul>
+<h2 id="NPAPI_Plugin_Test_Cases">NPAPI Plugin Test Cases</h2>
+<ul>
+ <li>mozilla.org QA <a class="external" href="http://www.mozilla.org/quality/browser/front-end/testcases/plugins/">Plugins testcases</a></li>
+ <li>mozilla.org QA <a class="external" href="http://www.mozilla.org/quality/browser/front-end/testcases/oji/">OJI testcases</a></li>
+ <li><a class="external" href="http://www.mozilla.org/projects/plugins/plugins_testing_checklist.html">Plugins Verification Testing Checklist</a> (including <a class="external" href="http://www.mozilla.org/quality/smoketests/">SmokeTesting</a>)</li>
+</ul>
+<p>{{ languages( { "de": "de/Plugins/Beispiele_und_Testfälle" } ) }}</p>
diff --git a/files/zh-cn/mozilla/add-ons/plugins/shipping_a_plugin_as_a_toolkit_bundle/index.html b/files/zh-cn/mozilla/add-ons/plugins/shipping_a_plugin_as_a_toolkit_bundle/index.html
new file mode 100644
index 0000000000..30aae2d422
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/plugins/shipping_a_plugin_as_a_toolkit_bundle/index.html
@@ -0,0 +1,56 @@
+---
+title: Shipping a plugin as an extension
+slug: Mozilla/Add-ons/Plugins/Shipping_a_plugin_as_a_Toolkit_bundle
+tags:
+ - Extensions
+ - Plugins
+translation_of: Archive/Plugins/Shipping_a_plugin_as_a_Toolkit_bundle
+---
+<p>One of the new features that is available in Firefox 1.5 is the ability to place browser plug-ins in a Firefox extension.</p>
+<p>Historically, most people have chosen to use an install.js script to install a plug-in. When this method is used, you can choose to either place the plug-in into the plugins directory, or place it into your own directory and modify the Windows registry to let Firefox know where to find the plug-in. The downside to this method is that once the plug-in is installed, it might be difficult for users to upgrade, uninstall, or disable the plug-in. As of Firefox 3 (and any Gecko 1.9 based application) the use of install.js scripts is no longer possible and plugins must either be shipped as an executable installer or as an extension as described here.</p>
+<h2 id="Bundle_structure" name="Bundle_structure">Bundle structure</h2>
+<p><a href="cn/Bundles">Toolkit bundles</a> can be used for all add-ons including extensions, themes and plugins. Plugin packages should only need to package a small set of files in the follow structure in the xpi file:</p>
+<pre>install.rdf
+plugins/
+ pluginlib.dll
+ plugintypes.xpt
+</pre>
+<p>The install.rdf file contains an <a href="#Install_Manifest">install manifest</a> that describes the plugin to the user. The library and scripting interfaces are held in the &lt;tt&gt;plugins&lt;/tt&gt; directory.</p>
+<h3 id="Platform-specific_files" name="Platform-specific_files">Platform-specific files</h3>
+<p>It is possible to package multiple plugin libraries for different operating systems into a single xpi bundle. In the xpi you can use the following structure:</p>
+<pre>platform/
+ Linux_x86-gcc3/
+ plugins/
+ libplugin.so
+ Darwin_ppc-gcc3/
+ plugins/
+ libplugin.dylib
+</pre>
+<p>More specific information can be found in the <a href="cn/Bundles#Platform-specific_Subdirectories">platform-specific subdirectories</a> documentation.</p>
+<h2 id="Install_Manifest" name="Install_Manifest">Install Manifest</h2>
+<p>The <a href="cn/Install.rdf">install manifest</a> describes the plugin to the user. For a plugin the manifest only needs to be very simple:</p>
+<pre>&lt;RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"&gt;
+ &lt;Description about="urn:mozilla:install-manifest"&gt;
+ &lt;em:id&gt;mypluginid@myplugin.com&lt;/em:id&gt;
+ &lt;em:name&gt;My Plugin&lt;/em:name&gt;
+ &lt;em:version&gt;1.0&lt;/em:version&gt;
+ &lt;em:targetApplication&gt;
+ &lt;Description&gt;
+ &lt;em:id&gt;{ec8030f7-c20a-464f-9b0e-13a3a9e97384}&lt;/em:id&gt;
+ &lt;em:minVersion&gt;1.5&lt;/em:minVersion&gt;
+ &lt;em:maxVersion&gt;3.0.*&lt;/em:maxVersion&gt;
+ &lt;/Description&gt;
+ &lt;/em:targetApplication&gt;
+ &lt;/Description&gt;
+&lt;/RDF&gt;
+</pre>
+<p>This contains 4 required pieces of information.</p>
+<ol>
+ <li>Every add-on must have a unique id. This can be in a guid form but the simpler email form is preferred now. You should aim to use a domain-name that you own and then your own unique short-name for the plugin before the @.</li>
+ <li>The plugin must have a name to identify the plugin to the user in the list of add-ons.</li>
+ <li>The version is fairly self-descriptive, it must be a <a href="cn/Toolkit_version_format">toolkit version format</a>.</li>
+ <li>The target application block says which versions of an application the plugin is compatible with. It includes the application ID and the minimum and maximum version of the application that the plugin works with. There can be multiple targetApplication blocks listed.</li>
+</ol>
+<h2 id="Providing_updates" name="Providing_updates">Providing updates</h2>
+<p>When plugins are packaged in this way they can make use of the built in add-on update system. This allows a remote update file to be read periodically and an updated version of the plugin offered to the user or to mark the plugin as compatible with a wider range of applications.</p>
+<p>This is performed by including an <a href="cn/Install.rdf#updateURL">updateURL</a> in the install manifest. This should point to an <a href="cn/Extension_Versioning%2c_Update_and_Compatibility#Update_RDF_Format">update.rdf</a> file on the internet which will include the updated versions and version information for the plugin.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/builder/index.html b/files/zh-cn/mozilla/add-ons/sdk/builder/index.html
new file mode 100644
index 0000000000..1baa282d43
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/builder/index.html
@@ -0,0 +1,13 @@
+---
+title: Builder
+slug: Mozilla/Add-ons/SDK/Builder
+translation_of: Archive/Add-ons/Add-on_SDK/Builder
+---
+<p>The Add-on Builder was a web-based development environment that allowed developers to create add-ons using the SDK APIs, but without needing to use the <code>cfx</code> command line tool. It was retired on April 1, 2014, and the "builder.addons.mozilla.org" domain now redirects to this page.<br>
+ <br>
+ If you have only used the SDK through the Builder, you already know most of what you need to know to develop using just the SDK. The <a href="/en-US/Add-ons/SDK/High-Level_APIs">high-level</a> and <a href="/en-US/Add-ons/SDK/Low-Level_APIs">low-level</a> APIs used for Builder add-ons are exactly the same for Builder and SDK. To switch to the SDK:</p>
+<ul>
+ <li><a href="/en-US/Add-ons/SDK/Tutorials/Installation">install the SDK locally</a></li>
+ <li>get to know the cfx command line tool, with this <a href="/en-US/Add-ons/SDK/Tutorials/Getting_started">introductory walkthrough</a> and the <a href="/en-US/Add-ons/SDK/Tools/cfx">detailed <code>cfx</code> reference</a></li>
+ <li>get to know the <a href="/en-US/Add-ons/SDK/Tools/package_json">package.json</a> file used to configure attributes of your add-on</li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/guides/content_scripts/index.html b/files/zh-cn/mozilla/add-ons/sdk/guides/content_scripts/index.html
new file mode 100644
index 0000000000..fa95b15db3
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/guides/content_scripts/index.html
@@ -0,0 +1,486 @@
+---
+title: Content Scripts(内容脚本)
+slug: Mozilla/Add-ons/SDK/Guides/Content_Scripts
+translation_of: Archive/Add-ons/Add-on_SDK/Guides/Content_Scripts
+---
+<article id="wikiArticle">{{AddonSidebar}}
+<p><span class="seoSummary">很多 add-ons 需要访问和修改 web 页面的内容。但是 add-on 的主代码不能直接访问 web 内容。替代方案是, SDK add-ons 需要使用一些分散的脚本代理访问 web 内容,这些脚本被称作<em>内容脚本(content scripts)</em>。本页面描述如何开发和部署内容脚本。 </span></p>
+
+<p>内容脚本是在使用SDK时很令人疑惑的点,但你很有可能不得不使用它们。下面有五个基本原则:</p>
+
+<ul>
+ <li>add-on 的主代码,包括"main.js"和其他"lib"下的模块,可以使用 SDK <a href="/zh-CN/docs/Mozilla/Add-ons/SDK/High-Level_APIs">高层次</a>和<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Low-Level_APIs">低层次</a> APIs,但不能直接访问 web 内容</li>
+ <li>内容脚本 <a href="/en-US/Add-ons/SDK/Guides/Two_Types_of_Scripts#API_Access_for_Add-on_Code_and_Content_Scripts">不能使用 SDK 的 API</a>(访问不了 globals 的 <code>exports</code>、<code>require</code>),但你可以访问 web 内容</li>
+ <li>SDK API 可以使用,内容脚本,比如 <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a> 和 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs">tabs</a>,提供了一些函数,使得 add-on 的主代码可以将内容脚本载入web页面中。</li>
+ <li>内容脚本可以作为字符串加载,但是更常见的是分离存储为 add-on 的"data"目录下文件。 jpm 不会默认创建"data"目录,所以你必须添加该目录并把脚本放进去。</li>
+ <li>一个消息传递 API 允许主代码和内容脚本间相互通信。</li>
+</ul>
+
+<p>这个完整的 add-on 表现出所有的这些原则。它的"main.js"使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs">tabs</a> 模块附加了一个内容脚本到当前标签页。本例中内容脚本作为字符串传递,内容脚本简单地替换了页面的内容:</p>
+
+<pre class="brush: js">// main.js
+var tabs = require("sdk/tabs");
+var contentScriptString = 'document.body.innerHTML = "&lt;h1&gt;this page has been eaten&lt;/h1&gt;";'
+
+tabs.activeTab.attach({
+ contentScript: contentScriptString
+});</pre>
+
+<p>下面的高层次 SDK 模块能使用内容脚本来修改 web 页面:</p>
+
+<ul>
+ <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a>:使你能附加一个内容脚本到匹配上特定 URL 模式的web页面。</li>
+ <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs">tabs</a>:导出一个 <code>Tab</code> 对象来处理浏览器标签页。<code>Tab</code> 对象包括了一个 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#attach(options)"><code>attach()</code></a> 函数来附加内容脚本到标签页。</li>
+ <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/page-worker">page-worker</a>:让你能够恢复一个 web 页面,但不显示它。你可以附加内容脚本到该页面,来访问和操作该页面的 DOM。</li>
+ <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu">context-menu</a>:使用内容脚本来和按钮所在的页面交互。</li>
+</ul>
+
+<p>另外,还能使用 HTML 定义了一些 SDK 用户接口组件,并且使用分类的脚本来和这些内容交互。从很多方面来讲,这些脚本就像内容脚本一样,但它们并不是本文的关注点。要学习如何和用户接口模块的内容交互,请参看模块定义文档:<a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a>、<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_sidebar">sidebar</a>、<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_frame">frame</a>。</p>
+
+<p>这篇指南中列出的几乎所有的示例都是完整并且且最小的,可以在 Github 的 <a href="https://github.com/mdn/addon-sdk-content-scripts">addon-sdk-content-scripts repository</a> 页面上获得。</p>
+
+<h2 id="加载用户脚本">加载用户脚本</h2>
+
+<article id="wikiArticle">
+<p>你可以声明一个字符串或者指定 <code>contentScript</code> 或 <code>contentScriptFile</code> 选项加载一个单独的脚本。<code>contentScript</code> 选项接受一个作为脚本的字符串:</p>
+
+<pre class="brush: js">// main.js
+
+var pageMod = require("sdk/page-mod");
+var contentScriptValue = 'document.body.innerHTML = ' +
+ ' "&lt;h1&gt;Page matches ruleset&lt;/h1&gt;";';
+
+pageMod.PageMod({
+ include: "*.mozilla.org",
+ contentScript: contentScriptValue
+});</pre>
+
+<p><code>contentScriptFile</code> 选项接受一个作为 resource:// URL 的字符串,指向一个存储在你的 add-on 的 <code>data</code> 目录中的脚本文件。jpm不会默认创建"data"目录,所以你必须创建该目录并将你的用户脚本放进去。</p>
+
+<p>本 add-on 提供一个 URL ,指向"content-script.js"文件,存储在 add-on 根目录下的 <code>data</code> 子目录:</p>
+
+<pre class="brush: js">// main.js
+
+var data = require("sdk/self").data;
+var pageMod = require("sdk/page-mod");
+
+pageMod.PageMod({
+ include: "*.mozilla.org",
+ contentScriptFile: data.url("content-script.js")
+});</pre>
+
+<pre class="brush: js">// content-script.js
+
+document.body.innerHTML = "&lt;h1&gt;Page matches ruleset&lt;/h1&gt;";</pre>
+
+<div class="note">
+<p>从 Firefox 34 开始,你可以使用"./content-script.js"替代 self.data.url("content-script.js")。所以你可以像这样重写:</p>
+
+<pre class="brush: js">var pageMod = require("sdk/page-mod");
+
+pageMod.PageMod({
+ include: "*.mozilla.org",
+ contentScriptFile: "./content-script.js"
+});
+</pre>
+</div>
+
+<div class="warning">
+<p>除非你的内容脚本非常简单并且固定是一个静态的字符串,请不要使用 <code>contentScript</code>:否则,你会在从 AMO 获取你的add-on上遇到问题。</p>
+
+<p>相反,把脚本放到一个单独的文件并用 <code>contentScriptFile</code> 加载它。这回事你的代码更易维护、安全、调试和审核。</p>
+</div>
+
+<p>你可以给 <code>contentScript</code> 或 <code>contentScriptFile</code> 传递字符串数组来加载多个脚本:</p>
+
+<pre class="brush: js">// main.js
+
+var tabs = require("sdk/tabs");
+
+tabs.on('ready', function(tab) {
+ tab.attach({
+ contentScript: ['document.body.style.border = "5px solid red";', 'window.alert("hi");']
+ });
+});
+</pre>
+
+<pre class="brush: js">// main.js
+
+var data = require("sdk/self").data;
+var pageMod = require("sdk/page-mod");
+
+pageMod.PageMod({
+ include: "*.mozilla.org",
+ contentScriptFile: [data.url("jquery.min.js"), data.url("my-content-script.js")]
+});</pre>
+
+<p>如果你这么做,这些脚本之间可以直接交互,就像他们被同一个 web 页面加载一样。</p>
+
+<p>你也可以把 <code>contentScript</code> 和 <code>contentScriptFile</code> 一起用。如果你这么做,使用 <code>contentScriptFile</code> 定义的脚本会在使用 <code>contentScript</code> 定义的脚本之前加载。这使你能够用 URL 加载比如 jQuery 这样的 JavaScript 库,然后传递一个简单的能够使用jQuery脚本:</p>
+
+<pre class="brush: js">// main.js
+
+var data = require("sdk/self").data;
+var pageMod = require("sdk/page-mod");
+
+var contentScriptString = '$("body").html("&lt;h1&gt;Page matches ruleset&lt;/h1&gt;");';
+
+pageMod.PageMod({
+ include: "*.mozilla.org",
+ contentScript: contentScriptString,
+ contentScriptFile: data.url("jquery.js")
+});</pre>
+
+<div class="warning">
+<p>除非你的内容脚本非常简单并且固定是一个静态的字符串,请不要使用 <code>contentScript</code>:否则,在从 AMO 获取你的 add-on 上,你会遇到问题。</p>
+
+<p>相反,把脚本放到一个单独的文件并用 <code>contentScriptFile</code> 加载它。这回事你的代码更易维护、安全、调试和审核。</p>
+</div>
+
+<h3 id="控制附加脚本的时间">控制附加脚本的时间</h3>
+
+<p><code>contentScriptWhen</code> 选项指定了什么时候加载内容脚本。从这里选一个:</p>
+
+<ul>
+ <li><code>"start"</code>:页面 document 元素插入 DOM 之后,立即加载脚本。这时 DOM 的内容仍未加载,所以脚本不能与其交互。</li>
+ <li><code>"ready"</code>:页面 DOM 加载完后加载脚本:也就是说,在那个时间点 <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> 事件触发。这时,内容脚本可以和DOM内容交互,但外部引用的样式表和图片可能还没有完成加载。</li>
+ <li><code>"end"</code>:页面上所有内容(DOM、JS、CSS、images)加载完后,加载脚本,就是在 <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload 事件</a>触发的时候</li>
+</ul>
+
+<p>默认值为 <code>"end"</code>。</p>
+
+<p>注意 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#attach(options)"><code>tab.attach()</code></a> 不支持 contentScriptWhen,因为它原来就是在页面加载页面的时候被调用的。</p>
+
+<h3 id="传递配置选项">传递配置选项</h3>
+
+<p><code>contentScriptOptions</code> 是一个作为只读对象暴露给内容脚本的JSON对象,在 <code><a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/self">self</a>.options</code> 的属性里:</p>
+
+<pre class="brush: js">// main.js
+
+var tabs = require("sdk/tabs");
+
+tabs.on('ready', function(tab) {
+ tab.attach({
+ contentScript: 'window.alert(self.options.message);',
+ contentScriptOptions: {"message" : "hello world"}
+ });
+});</pre>
+
+<p>这里可以使用任何可以转成json的值(object、array、string等等)。</p>
+
+<h2 id="访问_DOM">访问 DOM</h2>
+
+<p>内容脚本可以访问页面的 DOM,就像任何页面中加载的脚本(页面脚本)一样。但是内容脚本和页面脚本之间是隔离的:</p>
+
+<ul>
+ <li>内容脚本不能看到任何由页面脚本添加到页面的 JavaScript 对象</li>
+ <li>如果页面脚本重定义了某个 DOM 对象的行为,但内容脚本只会看到原来的那个行为。</li>
+</ul>
+
+<p>相反也是如此:页面脚本不能看到内容脚本添加的 JavaScript 对象。</p>
+
+<p>例如,假想一个页面用页面脚本添加变量 <code>foo</code> 到 <code>window</code> 对象:</p>
+
+<pre class="brush: html">&lt;!DOCTYPE html"&gt;
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;script&gt;
+ window.foo = "hello from page script"
+ &lt;/script&gt;
+ &lt;/head&gt;
+&lt;/html&gt;</pre>
+
+<p>在这个脚本后面加载到页面的其他脚本也可以访问 <code>foo</code>。但是内容脚本不能:</p>
+
+<pre class="brush: js">// main.js
+
+var tabs = require("sdk/tabs");
+var mod = require("sdk/page-mod");
+var self = require("sdk/self");
+
+var pageUrl = self.data.url("page.html")
+
+var pageMod = mod.PageMod({
+ include: pageUrl,
+ contentScript: "console.log(window.foo);"
+})
+
+tabs.open(pageUrl);</pre>
+
+<pre>console.log: my-addon: null
+</pre>
+
+<p>这种隔离策略有着很合理的理由。首先,这意味着内容脚本不会泄露对象给 web 页面,这样可能会打开安全漏洞。第二,这意味着,在内容脚本创建对象的时候,可以不用担心是否会和页面脚本添加的对象相冲突。</p>
+
+<p>这种隔离意味着,例如,如果一个 web 页面加载了 jQuery 库,那么内容脚本不能够看到由该库添加的 <code>jQuery</code> 对象——但是可以看到内容脚本添加的自己的 <code>jQuery</code> 对象,并且它不会和页面脚本的 jQuery 版本冲突。</p>
+
+<h3 id="和页面脚本交互">和页面脚本交互</h3>
+
+<p>一般来说,这种内容脚本和页面脚本的隔离正是你所希望的。但是有时候你也许会希望和页面脚本交互:你想在内容脚本和页面脚本之间共享对象来,来在它们之间发送消息。如果你需要这么做,请阅读<a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/Interacting_with_page_scripts">和页面脚本交互</a>。</p>
+
+<h3 id="事件监听器">事件监听器</h3>
+
+<p>你可以监听 DOM 的事件,就像在页面脚本中一样,但是有两个重要的区别:</p>
+
+<p>第一,如果你向 <a href="https://developer.mozilla.org/en/DOM/element.setAttribute"><code>setAttribute()</code></a> 传递字符串,来定义了事件监听器,那么此监听器被当做是在页面上下文中的,所以它不能访问任何内容脚本中的变量。</p>
+
+<p>如下,内容脚本会失败报错"theMessage is not defined":</p>
+
+<pre class="brush: js">var theMessage = "Hello from content script!";
+anElement.setAttribute("onclick", "alert(theMessage);");</pre>
+
+<p>Second, if you define an event listener by direct assignment to a <a href="/en-US/docs/Web/API/GlobalEventHandlers">global event handler</a> like <code>onclick</code>, then the assignment might be overridden by the page. For example, here's an add-on that tries to add a click handler by assignment to <code>window.onclick</code>:</p>
+
+<pre class="brush: js">var myScript = "window.onclick = function() {" +
+ " console.log('unsafewindow.onclick: ' + window.document.title);" +
+ "}";
+
+require("sdk/page-mod").PageMod({
+ include: "*",
+ contentScript: myScript,
+ contentScriptWhen: "start"
+});</pre>
+
+<p>这个示例会在大多数页面上正常工作,但是会在定义 <code>onclick</code> 的页面上失败:</p>
+
+<pre class="brush: html">&lt;html&gt;
+ &lt;head&gt;
+ &lt;/head&gt;
+ &lt;body&gt;
+ &lt;script&gt;
+ window.onclick = function() {
+ window.alert("it's my click now!");
+ }
+ &lt;/script&gt;
+ &lt;/body&gt;
+&lt;/html&gt;</pre>
+
+<p>由于这些原因,最好还是用 <a href="https://developer.mozilla.org/en/DOM/element.addEventListener"><code>addEventListener()</code> 添加一个事件监听器</a>,定义监听器为一个函数:</p>
+
+<pre class="brush: js">var theMessage = "Hello from content script!";
+
+anElement.onclick = function() {
+ alert(theMessage);
+};
+
+anotherElement.addEventListener("click", function() {
+ alert(theMessage);
+});</pre>
+
+<h2 id="和_add-on_通信">和 add-on 通信</h2>
+
+<p>为了使 add-on 脚本和内容脚本相互通信,任何一通信端都要访问 <code>port</code> 对象。</p>
+
+<ul>
+ <li>要从一头发送消息到另一头,使用 <code>port.emit()</code></li>
+ <li>要从另一头接收消息,使用 <code>port.on()</code></li>
+</ul>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/7873/content-scripting-overview.png" style="display: block; margin-left: auto; margin-right: auto;">消息是异步的:也就是说,发送方不会等待接收方的回应,而仅仅是发送消息完后继续处理别的事情。</p>
+
+<p>这里有一个简单的 add-on 使用 <code>port</code> 发送一个消息到内容脚本:</p>
+
+<pre class="brush: js">// main.js
+
+var tabs = require("sdk/tabs");
+var self = require("sdk/self");
+
+tabs.on("ready", function(tab) {
+ var worker = tab.attach({
+ contentScriptFile: self.data.url("content-script.js")
+ });
+ worker.port.emit("alert", "Message from the add-on");
+});
+
+tabs.open("http://www.mozilla.org");</pre>
+
+<pre class="brush: js">// content-script.js
+
+self.port.on("alert", function(message) {
+ window.alert(message);
+});</pre>
+
+<div class="note">
+<p>context-menu 模块没有使用这里描述的通信模型。了解更多关于使用 context-menu 和内容脚本通信的事情,参看 <a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu">context-menu documentation</a>。</p>
+</div>
+
+<h3 id="在内容脚本中访问_port"><code>在内容脚本中访问 port</code></h3>
+
+<p>内容脚本中,<code>port</code> 对象是作为global下 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/self"><code>self</code></a> 对象的属性。所以要从内容脚本中发送消息的话:</p>
+
+<pre class="brush: js">self.port.emit("myContentScriptMessage", myContentScriptMessagePayload);</pre>
+
+<p>要从 add-on 代码接收消息</p>
+
+<pre class="brush: js">self.port.on("myAddonMessage", function(myAddonMessagePayload) {
+ // Handle the message
+});</pre>
+
+<div class="note">
+<p>注意 global下 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/self"><code>self</code></a> 对象和 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code> 模块</a>完全不一样,后者提供一个API给 add-on,用来访问它的数据文件和ID。</p>
+</div>
+
+<h3 id="在内容脚本中访问_port_2">在内容脚本中访问 port</h3>
+
+<p>在 add-on 代码中,联通 add-on 和某一特定内容脚本上下文的通道被封装入 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/content_worker"><code>worker</code></a> 对象。所以和内容脚本通信的 <code>port</code> 对象其实是其相对应的 <code>worker</code> 对象的一个属性。</p>
+
+<p>但是,这个 worker 没有暴露给 add-on 代码,以及同样所有的模块。</p>
+
+<h4 id="从_page-worker">从 <code>page-worker</code></h4>
+
+<p><code>page-worker</code> 对象直接整合了 work API。所以要从一个由 <code>page-worker</code> 关联的内容脚本接收消息的话,你可以使用 <code>pageWorker.port.on()</code>:</p>
+
+<pre class="brush: js">// main.js
+
+var self = require("sdk/self");
+
+var pageWorker = require("sdk/page-worker").Page({
+  contentScriptFile: self.data.url("content-script.js"),
+  contentURL: "http://en.wikipedia.org/wiki/Internet"
+});
+
+pageWorker.port.on("first-para", function(firstPara) {
+  console.log(firstPara);
+});</pre>
+
+<p>要从你的 add-on 发送用户定义的消息,你可以只调用 <code>pageWorker.port.emit()</code>:</p>
+
+<pre class="brush: js">// main.js
+
+var self = require("sdk/self");
+
+var pageWorker = require("sdk/page-worker").Page({
+  contentScriptFile: self.data.url("content-script.js"),
+  contentURL: "http://en.wikipedia.org/wiki/Internet"
+});
+
+pageWorker.port.on("first-para", function(firstPara) {
+  console.log(firstPara);
+});
+
+pageWorker.port.emit("get-first-para");</pre>
+
+<pre class="brush: js">// content-script.js
+
+self.port.on("get-first-para", getFirstPara);
+
+function getFirstPara() {
+ var paras = document.getElementsByTagName("p");
+ if (paras.length &gt; 0) {
+ var firstPara = paras[0].textContent;
+ self.port.emit("first-para", firstPara);
+ }
+}</pre>
+
+<h4 id="从_page-mod">从<code> page-mod</code></h4>
+
+<p>单个 <code>page-mod</code> 对象可以附加它的脚本到多个页面,每个页面有它自己的上下文来运行内容脚本,所以每个页面都需要相互隔离的通道(worker)。</p>
+
+<p>所以 <code>page-mod</code> 没有直接整合 worker 的 API。而是在每次内容脚本被附加到页面时,page-mod 发送一个 <code>attach</code> 事件,它的监听器会给对应的上下文传递一个 worker。通过为 <code>attach</code> 提供一个监听器,你可以访问被一个 page-mod 附加到页面上的内容脚本的 <code>port</code> 对象:</p>
+
+<pre class="brush: js">// main.js
+
+var pageMods = require("sdk/page-mod");
+var self = require("sdk/self");
+
+var pageMod = pageMods.PageMod({
+  include: ['*'],
+  contentScriptFile: self.data.url("content-script.js"),
+  onAttach: startListening
+});
+
+function startListening(worker) {
+  worker.port.on('click', function(html) {
+    worker.port.emit('warning', 'Do not click this again');
+  });
+}</pre>
+
+<pre class="brush: js">// content-script.js
+
+window.addEventListener('click', function(event) {
+ self.port.emit('click', event.target.toString());
+ event.stopPropagation();
+ event.preventDefault();
+}, false);
+
+self.port.on('warning', function(message) {
+ window.alert(message);
+});
+</pre>
+
+<p>上面的 add-on 里有两条消息:</p>
+
+<ul>
+ <li>当用户点击页面元素时,<code>click</code> 从 page-mod 被发送到当前 add-on。</li>
+ <li><code>warning</code> 发送一条傻气的字符串回给page-mod</li>
+</ul>
+
+<h4 id="从_Tab.attach()">从 <code>Tab.attach()</code></h4>
+
+<p><code>Tab.attach()</code> 方法返回一个 worker,你可以用来和附加的内容脚本通信。</p>
+
+<p>这个 add-on 添加了一个按钮到Firefox:等用户点击按钮是,这个 add-on 附加一个内容脚本到当前的标签页,发送给内容脚本一条名为 "my-addon-message"的消息,并且监听名为"my-script-response"的响应:</p>
+
+<pre class="brush: js">//main.js
+
+var tabs = require("sdk/tabs");
+var buttons = require("sdk/ui/button/action");
+var self = require("sdk/self");
+
+buttons.ActionButton({
+ id: "attach-script",
+ label: "Attach the script",
+ icon: "./icon-16.png",
+ onClick: attachScript
+});
+
+function attachScript() {
+ var worker = tabs.activeTab.attach({
+ contentScriptFile: self.data.url("content-script.js")
+ });
+ worker.port.on("my-script-response", function(response) {
+ console.log(response);
+ });
+ worker.port.emit("my-addon-message", "Message from the add-on");
+}
+</pre>
+
+<pre class="brush: js">// content-script.js
+
+self.port.on("my-addon-message", handleMessage);
+
+function handleMessage(message) {
+ alert(message);
+ self.port.emit("my-script-response", "Response from content script");
+}</pre>
+
+<h3 id="port的API">port的API</h3>
+
+<p>参看 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/port"><code>port</code> 对象的参考文档</a>.</p>
+</article>
+
+<h3 id="postMessage的API">postMessage的API</h3>
+
+<p>在 <code>port</code> 对象加载之前,add-on 代码和内容脚本可以使用另一个 API 通信:</p>
+
+<ul>
+ <li>内容脚本调用 <code>self.postMessage()</code> 来发送,并用 <code>self.on()</code> 来接收</li>
+ <li>内容脚本调用 <code>worker.postMessage()</code> 来发送,并用 <code>worker.on()</code> 来接收</li>
+</ul>
+
+<p>这个API依然可用,并且还有<a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_postMessage">文档</a>,但是没有理由替代前文描述的 <code>port</code> API。 例外是 <a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu">context-menu</a> 模块,它还是使用 postMessage。</p>
+
+<h3 id="内容脚本的内容脚本">内容脚本的内容脚本</h3>
+
+<p>内容脚本可用直接和其他同一个上下文中的内容脚本通信。举个例子,如果一次 <code>Tab.attach()</code> 的调用附加了两个脚本,那么他们可用直接相互查看,就像加载在同一页面内的页面脚本一样。但是如果你调用 <code>Tab.attach()</code> 两次,每次附加一个内容脚本,那么这些内容脚本之间不能通信。你必须使用port API 通过 add-on 的主代码来传递消息。</p>
+
+<h2 id="跨域的内容脚本">跨域的内容脚本</h2>
+
+<p>默认情况下,内容脚本没有跨域的权限。特别是,它们不能访问在不同 <code>iframe</code> 中的在另外的域名上的内容,也不能发起跨域的 XMLHttpRequests。</p>
+
+<p>但是,你可以把需要的域名添加到 <a href="/en-US/Add-ons/SDK/Tools/package_json">package.json</a> 中<code>"permissions"</code>键下的 <code>"cross-domain-content"</code>键下,为这些域名打开这些特性。参阅文章<a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/Cross_Domain_Content_Scripts">跨域内容脚本</a>。</p>
+</article>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/guides/index.html b/files/zh-cn/mozilla/add-ons/sdk/guides/index.html
new file mode 100644
index 0000000000..51fbdef445
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/guides/index.html
@@ -0,0 +1,115 @@
+---
+title: 教程
+slug: Mozilla/Add-ons/SDK/Guides
+tags:
+ - NeedsTranslation
+ - TopicStub
+translation_of: Archive/Add-ons/Add-on_SDK/Guides
+---
+<p>下面列出了一些文章可以加深你对SDK的理解</p>
+<hr>
+<h3 id="投稿者的教程"><a name="contributors-guide">投稿者的教程</a></h3>
+<div class="column-container">
+ <div class="column-half">
+ <dl>
+ <dt>
+ <a href="Guides/Getting_Started">起步</a></dt>
+ <dd>
+ 学会如何使用SDK : 编写代码, 调试bug, 提交补丁, 审核项目, 获得帮助.</dd>
+ <dt>
+ <a href="Guides/Modules">模块</a></dt>
+ <dd>
+ 通过SDK学会模块的使用 (以CommonJS为规范), 懂得如何使用 sandboxes 和compartments 提高安全性, 并且了解内置的 SDK module loader (被称为Cuddlefish).</dd>
+ <dt>
+ <a href="Guides/Classes_and_Inheritance">类 和 继承</a></dt>
+ <dd>
+ 学会<strong> 类</strong>和<strong>继承</strong>在JavaScript中的运行机制, 使用<strong>构造(constructors)</strong>和<strong>原型(prototypes)</strong>, 并知道如何使用SDK提供的函数帮助器简化它.</dd>
+ </dl>
+ </div>
+ <div class="column-half">
+ <dl>
+ <dt>
+ <a href="Guides/Private_Properties">私有成员</a></dt>
+ <dd>
+ 通过 前缀, 闭包, 和WeakMaps 学会私有成员如何在JavaScript中的实现, 使用 命名空间(通常指WeakMaps) 学会SDK如何支持私有成员.</dd>
+ <dt>
+ <a href="Guides/Content_Processes">脚本运行流程</a></dt>
+ <dd>
+ SDK的设计目的是为了使控制网页内容的扩展脚本可以在不同进程的环境中运行. 这篇文章强调了这一设计的特点.</dd>
+ </dl>
+ </div>
+</div>
+<hr>
+<h3 id="SDK的基础结构"><a name="sdk-infrastructure">SDK的基础结构</a></h3>
+<div class="column-container">
+ <div class="column-half">
+ <dl>
+ <dt>
+ <a href="Guides/Module_structure_of_the_SDK">SDK 模块结构</a></dt>
+ <dd>
+ SDK是可重复使用的 JavaScript 模块. 这里解释了什么是模块, 怎样加载模块, 和SDK模块树的构造.</dd>
+ <dt>
+ <a href="Guides/SDK_API_Lifecycle">SDK API 生存周期</a></dt>
+ <dd>
+ 为SDK的API定义生命周期,  包括API稳定性的排名</dd>
+ </dl>
+ </div>
+ <div class="column-half">
+ <dl>
+ <dt>
+ <a href="Guides/Program_ID">程序 ID</a></dt>
+ <dd>
+ 程序ID 是扩展独一无二的标识符. 教程解释了如何定义你自己的程序 ID.</dd>
+ <dt>
+ <a href="Guides/Firefox_Compatibility">Firefox 兼容</a></dt>
+ <dd>
+ 解决不同版本SDK生成的扩展与不同版本Firefox的兼容问题</dd>
+ </dl>
+ </div>
+</div>
+<hr>
+<h3 id="SDK_常用技巧"><a name="sdk-idioms">SDK 常用技巧</a></h3>
+<div class="column-container">
+ <div class="column-half">
+ <dl>
+ <dt>
+ <a href="Guides/Working_with_Events">善用 事件触发</a></dt>
+ <dd>
+ 通过SDK的事件触发框架 写出以事件驱动为基础的代码</dd>
+ </dl>
+ </div>
+ <div class="column-half">
+ <dl>
+ <dt>
+ <a href="Guides/Two_Types_of_Scripts">脚本的两种类型</a></dt>
+ <dd>
+ 这篇文章可以帮助你理解扩展中的API和普通脚本的区别</dd>
+ </dl>
+ </div>
+</div>
+<p> </p>
+<hr>
+<h3 id="XUL_迁移"><a name="xul-migration">XUL 迁移</a></h3>
+<div class="column-container">
+ <div class="column-half">
+ <dl>
+ <dt>
+ <a href="Guides/XUL_Migration_Guide">XUL 迁移教程</a></dt>
+ <dd>
+ 把XUL扩展迁移到SDK的技巧</dd>
+ <dt>
+ <a href="Guides/XUL_vs_SDK">XUL 与 SDK 不同</a></dt>
+ <dd>
+ 比较 传统的以XUL为基础的扩展 和 SDK 两者优点和缺点</dd>
+ </dl>
+ </div>
+ <div class="column-half">
+ <dl>
+ <dt>
+ <a href="Guides/Porting_the_Library_Detector">移植例子</a></dt>
+ <dd>
+ 一个简单地教你如何让 基于XUL的扩展 迁移到 SDK中的实例</dd>
+ </dl>
+ </div>
+</div>
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/guides/multiprocess_firefox_and_the_sdk/index.html b/files/zh-cn/mozilla/add-ons/sdk/guides/multiprocess_firefox_and_the_sdk/index.html
new file mode 100644
index 0000000000..c22dd0181e
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/guides/multiprocess_firefox_and_the_sdk/index.html
@@ -0,0 +1,212 @@
+---
+title: 多进程 Firefox 与 SDK
+slug: Mozilla/Add-ons/SDK/Guides/Multiprocess_Firefox_and_the_SDK
+translation_of: Archive/Add-ons/Add-on_SDK/Guides/Multiprocess_Firefox_and_the_SDK
+---
+<p>我们目前正在使 Firefox 变为多进程,它为浏览器界面使用一个操作系统进程,为运行的网页使用另一个进程来执行代码,这个项目被称为 "electrolysis" 或者 "e10s"。更多信息请参考<a href="/en-US/Firefox/Multiprocess_Firefox">多进程 Firefox 相关页面</a>。</p>
+
+<p>本文章介绍了开发者如何测试基于 SDK 的附加组件是否与多进程的 Firefox 兼容,以及如何解决出现的问题。</p>
+
+<h2 id="SDK_的合约">SDK 的合约</h2>
+
+<p>SDK 为附加组件的开发者承诺了:</p>
+
+<ul>
+ <li><a href="/en-US/Add-ons/SDK/High-Level_APIs">顶层 API</a> 对多进程 Firefox 完全工作。如果并没有,请报告为 SDK 中的 bug。</li>
+ <li><a href="/en-US/Add-ons/SDK/Low-Level_APIs">底层 API</a> 也许不工作。如果你在使用底层 API,考虑检查、测试和重构某些代码。</li>
+</ul>
+
+<p>在实践中,大多数底层 API 将正常工作,但可以直接访问网页内容的底层 API 无法正常工作。</p>
+
+<h2 id="兼容性垫片">兼容性垫片</h2>
+
+<p>举例来说,你可能认为这是行不通的:</p>
+
+<pre class="brush: js">var contentDocument = require("sdk/window/utils")
+ .getMostRecentBrowserWindow().content.document;</pre>
+
+<p>但是,Firefox 为附加组件提供了许多 API 的兼容性垫片。这意味着许多 API,包括上述例子的那个,仍然工作。虽然有两条警示需注意:</p>
+
+<ul>
+ <li>这些垫片不完美:某些附加组件在有垫片的情况下仍然不工作。举例来说,许多垫片通过为内容对象返回跨进称对象包装器来工作,并且这<a href="/en-US/Firefox/Multiprocess_Firefox/Cross_Process_Object_Wrappers#Limitations_of_CPOWs">并非始终以同样的方式</a>作为内容对象。</li>
+ <li>这些垫片可能对性能有不良影响,我们希望人们最终去除它们。</li>
+</ul>
+
+<p>We don't yet have a complete list of low-level APIs that are not multiprocess compatible: that is, will not work without the shims. Where we know that a low-level API is not multiprocess compatible, we've indicated that in the documentation page for it.</p>
+
+<h2 id="测试">测试</h2>
+
+<p>To test whether an add-on works without the shims, use the <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">"multiprocess" permission</a>.</p>
+
+<div class="note">
+<p><strong>Note</strong> that you can only do this if you are using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>. You can't use the <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">"multiprocess" permission</a> if you are using <a href="/en-US/Add-ons/SDK/Tools/cfx">cfx</a>.</p>
+</div>
+
+<p>Setting this permission will disable the shims for your add-on, so you can test to see if it's really multiprocess compatible or not.</p>
+
+<p>However, there's a catch: some of the SDK's APIs themselves still depend on the shims. So by setting the <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">"multiprocess" permission</a>, your add-on might not work, even if you are only using high-level APIs. For example:</p>
+
+<pre class="brush: js">var selection = require("sdk/selection");
+
+function myListener() {
+ console.log(selection.text);
+}
+
+selection.on('select', myListener);
+</pre>
+
+<p>This add-on will not work if you've set the <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">"multiprocess" permission</a>, because <code><a href="/en-US/Add-ons/SDK/High-Level_APIs/selection">sdk/selection</a></code> depends on the shims. We're working on fixing these problems: see <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1004745">bug 1004745</a> and its dependencies.</p>
+
+<h2 id="使用框架脚本">使用框架脚本</h2>
+
+<p>If the shims don't enable your add-on to work properly, or you're trying to remove your dependency on the shims, then the solution is the same as it is for all add-ons:</p>
+
+<ul>
+ <li>factor the code that needs access to content objects into frame scripts</li>
+ <li>use the message manager to load the frame scripts into the content process</li>
+ <li>use the message manager to exchange messages with the frame scripts</li>
+</ul>
+
+<p>In the rest of this section we'll outline some SDK-specific details of using the message manager. However, you'll also need to read the main <a href="/en-US/Firefox/Multiprocess_Firefox/The_message_manager">message manager documentation</a> for the details on working with frame scripts.</p>
+
+<div class="note">
+<p>If you're used to working with content scripts in the SDK, then frame scripts might feel similar, but they're actually very different. Frame scripts are more like a part of the main add-on code that just happens to be running in the content process.</p>
+
+<p>Differences between frame scripts and content scripts include:</p>
+
+<ul>
+ <li>the <a href="/en-US/Firefox/Multiprocess_Firefox/Frame_script_environment">environment for frame scripts</a> and the <a href="/en-US/Add-ons/SDK/Guides/Two_Types_of_Scripts#API_Access_for_Add-on_Code_and_Content_Scripts">environment for content scripts</a> are totally different:
+
+ <ul>
+ <li>content scripts have a very similar environment to scripts loaded by web pages, plus the <code><a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/self">self</a></code> global.</li>
+ <li>frame scripts also have access to web content, but have a different set of APIs for communicating with the chrome process, and access to the <a href="/en-US/docs/Components_object">Components object</a>, which enables them to use privileged <a href="/en-US/docs/Mozilla/Tech/XPCOM">XPCOM</a> APIs and load <a href="/en-US/docs/Mozilla/JavaScript_code_modules">JSMs</a>.</li>
+ </ul>
+ </li>
+ <li>content scripts are reloaded when a new document is loaded. Frame scripts aren't: once a frame script is loaded into a tab it remains loaded until the tab is closed. For more details, see the article on <a href="/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Frame_script_loading_and_lifetime">frame script lifetime</a>.</li>
+</ul>
+</div>
+
+<h3 id="访问消息管理器">访问消息管理器</h3>
+
+<h4 id="全局消息管理器">全局消息管理器</h4>
+
+<p>To access the <a href="/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview#Global_frame_message_manager">global message manager</a>, you load the <a href="/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIMessageListenerManager">nsIMessageListenerManager</a> service. Before you can do this in an SDK add-on, you have to <code>require("chrome")</code> to get access to the <code><a href="/en-US/docs/Components_object">Components</a></code> object:</p>
+
+<pre class="brush: js">const {Cc, Ci} = require("chrome");
+
+var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+ .getService(Ci.nsIMessageListenerManager);</pre>
+
+<h4 id="窗口消息管理器">窗口消息管理器</h4>
+
+<p>The <a href="/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview#Window_message_manager">window message manager</a> is available as the <code>messageManager</code> property of a chrome window. To understand what a chrome window is, you need to distinguish three sorts of windows:</p>
+
+<ul>
+ <li>a content window is the <a href="/en-US/docs/Web/API/Window">Window</a> object familiar to Web developers as the global object for JavaScript loaded from an HTML document. This is the same window that content scripts in the SDK access.</li>
+ <li>a chrome window, also called a browser window. This is a Firefox application window, hosting the Firefox UI as well as a collection of tabs, each of which can in turn host a DOM window to display web content. This is the global for traditional overlay-based add-ons. In the SDK, the low-level <a href="/en-US/Add-ons/SDK/Low-Level_APIs/window_utils">window/utils</a> module works with these sorts of windows.</li>
+ <li>an SDK window, as made available by the high level <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows">windows</a> module. Each SDK window maps to a chrome window, but omits most of the chrome window's properties, including <code>messageManager</code>. If you have an SDK window you can convert it to a chrome window using <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows#Converting_to_chrome_windows">viewFor</a>.</li>
+</ul>
+
+<p>So to get a window message manager from the SDK, you have a couple of options:</p>
+
+<p>(1) Use the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/window_utils">window/utils</a> module:</p>
+
+<pre class="brush: js">// Note that although this code uses window/utils,
+// it's safe to run in the chrome process because
+// it only accesses chrome objects.
+
+// get the active chrome window
+var browserWindow = require("sdk/window/utils").getMostRecentBrowserWindow();
+
+var windowMM = browserWindow.messageManager;</pre>
+
+<p>(2) Use <code>viewFor</code> to convert an SDK window to a chrome window:</p>
+
+<pre class="brush: js">// get the active SDK window
+var windows = require("sdk/windows").browserWindows;
+var activeWindow = windows.activeWindow;
+
+// convert it to a chrome window
+var browserWindow = require("sdk/view/core").viewFor(activeWindow);
+
+var windowMM = browserWindow.messageManager;</pre>
+
+<h4 id="浏览器消息管理器">浏览器消息管理器</h4>
+
+<p>The <a href="/en-US/Firefox/Multiprocess_Firefox/Message_Manager/Message_manager_overview#Browser_message_manager">browser message manager</a> is available as the <code>messageManager</code> property of an XUL <code><a href="/en-US/docs/XUL/browser">browser</a></code>.</p>
+
+<p>In the SDK, to get a <code>browser</code> for a given tab, you can use the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/tabs_utils">tabs/utils</a> module's <code><a href="/en-US/Add-ons/SDK/Low-Level_APIs/tabs_utils#getBrowserForTab%28tab%29">getBrowserForTab</a></code> function. <code>getBrowserForTab</code> expects an XUL tab as an argument, so if you have an <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs">SDK tab</a> object, you'll need to convert it to an XUL tab using <code><a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#Converting_to_XUL_tabs">viewFor</a></code>:</p>
+
+<pre class="brush: js">// get the active SDK tab
+var tab = require("sdk/tabs").activeTab;
+// convert it to an XUL tab
+var xulTab = require("sdk/view/core").viewFor(tab);
+// get the XUL browser for this tab
+var xulBrowser = require("sdk/tabs/utils").getBrowserForTab(xulTab);
+
+var browserMM = xulBrowser.messageManager;</pre>
+
+<p>Again, although this code uses tabs/utils, it's safe to run in the chrome process because it only accesses chrome objects.</p>
+
+<h3 id="载入框架脚本">载入框架脚本</h3>
+
+<p>You can load frame scripts using the message manager, passing in a chrome:// or resource:// URL pointing to the script. With the SDK, the simplest approach is to keep frame scripts under your add-on's data directory, and pass in a resource:// URL created using <a href="/en-US/Add-ons/SDK/High-Level_APIs/self#data.url(name)">self.data.url</a>:</p>
+
+<pre class="brush: js">const self = require("sdk/self");
+
+messageManager.loadFrameScript(self.data.url("frame-script.js"), false);</pre>
+
+<p>Note that unlike the APIs to load content scripts, you can only load a single frame script here.</p>
+
+<h3 id="例子">例子</h3>
+
+<p>For example, this add-on trivially accesses content directly using a low-level API:</p>
+
+<pre class="brush: js">function logContent() {
+ var contentDocument = require("sdk/window/utils")
+ .getMostRecentBrowserWindow().content.document;
+ console.log(contentDocument.body.innerHTML);
+}
+
+require("sdk/ui/button/action").ActionButton({
+ id: "log-content",
+ label: "Log Content",
+ icon: "./icon-16.png",
+ onClick: logContent
+});</pre>
+
+<p>This add-on will work by default due to the shims, but will break if you set multiprocessCompatible. So you could rewrite the add-on to use frame scripts:</p>
+
+<pre class="brush: js">/*
+frame-script.js is in the "data" directory, and has this content:
+
+sendAsyncMessage("sdk-low-level-apis-e10s@jetpack:got-content",
+ content.document.body.innerHTML);
+
+*/
+
+const self = require("sdk/self");
+
+function logContentAsync() {
+ var tab = require("sdk/tabs").activeTab;
+ var xulTab = require("sdk/view/core").viewFor(tab);
+ var xulBrowser = require("sdk/tabs/utils").getBrowserForTab(xulTab);
+
+ var browserMM = xulBrowser.messageManager;
+ browserMM.loadFrameScript(self.data.url("frame-script.js"), false);
+ browserMM.addMessageListener("sdk-low-level-apis-e10s@jetpack:got-content",
+ logContent);
+}
+
+function logContent(message) {
+ console.log(message.data);
+}
+
+require("sdk/ui/button/action").ActionButton({
+ id: "log-content",
+ label: "Log Content",
+ icon: "./icon-16.png",
+ onClick: logContentAsync
+});</pre>
+
+<p>现在附加组件能正常工作了,即使你设置了 multiprocessCompatible。</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/guides/working_with_events/index.html b/files/zh-cn/mozilla/add-ons/sdk/guides/working_with_events/index.html
new file mode 100644
index 0000000000..4c24b84e13
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/guides/working_with_events/index.html
@@ -0,0 +1,122 @@
+---
+title: Working with Events
+slug: Mozilla/Add-ons/SDK/Guides/Working_with_Events
+translation_of: Archive/Add-ons/Add-on_SDK/Guides/Working_with_Events
+---
+<p>The Add-on SDK supports event-driven programming.</p>
+<p>Objects emit events on state changes that might be of interest to add-on code, such as browser windows opening, pages loading, network requests completing, and mouse clicks. By registering a listener function to an event emitter an add-on can receive notifications of these events.</p>
+<p><span>We talk about content scripts in more detail in the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> guide.</span></p>
+<p>Additionally, if you're using content scripts to interact with web content, you can define your own events and use them to communicate between the main add-on code and the content scripts. In this case one end of the conversation emits the events, and the other end listens to them.</p>
+<p>So there are two main ways you will interact with the EventEmitter framework:</p>
+<ul>
+ <li>
+ <p><strong>listening to built-in events</strong> emitted by objects in the SDK, such as tabs opening, pages loading, mouse clicks</p>
+ </li>
+ <li>
+ <p><strong>sending and receiving user-defined events</strong> between content scripts and add-on code</p>
+ </li>
+</ul>
+<p>This guide only covers the first of these; the second is explained in the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> guide.</p>
+<h2 id="Adding_Listeners">Adding Listeners</h2>
+<p>You can add a listener to an event emitter by calling its <code>on(type, listener)</code> method.</p>
+<p>It takes two parameters:</p>
+<ul>
+ <li>
+ <p><strong><code>type</code></strong>: the type of event we are interested in, identified by a string. Many event emitters may emit more than one type of event: for example, a browser window might emit both <code>open</code> and <code>close</code> events. The list of valid event types is specific to an event emitter and is included with its documentation.</p>
+ </li>
+ <li>
+ <p><strong><code>listener</code></strong>: the listener itself. This is a function which will be called whenever the event occurs. The arguments that will be passed to the listener are specific to an event type and are documented with the event emitter.</p>
+ </li>
+</ul>
+<p>For example, the following add-on registers a listener with the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> module to listen for the <code>ready</code> event, and logs a string to the console reporting the event:</p>
+<pre class="brush: js">var tabs = require("sdk/tabs");
+
+tabs.on("ready", function () {
+ console.log("tab loaded");
+});
+</pre>
+<p>It is not possible to enumerate the set of listeners for a given event.</p>
+<p>The value of <code>this</code> in the listener function is the object that emitted the event.</p>
+<h3 id="Listening_to_all_events">Listening to all events</h3>
+<div class="note">
+ <p>This example uses the <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> API, which is only available from Firefox 29 onwards.</p>
+</div>
+<p>From Firefox 28 onwards, you can pass the wildcard "*" as the <code>type</code> argument. If you do this, the listener will be called for any event emitted by that object, and its argument will be the name of the event:</p>
+<pre class="brush: js">var ui = require('sdk/ui');
+var panels = require("sdk/panel");
+var self = require("sdk/self");
+
+var panel = panels.Panel({
+ contentURL: self.data.url("panel.html")
+});
+
+panel.on("*", function(e) {
+ console.log("event " + e + " was emitted");
+});
+
+var button = ui.ActionButton({
+ id: "my-button",
+ label: "my button",
+ icon: "./icon-16.png",
+ onClick: handleClick
+});
+
+function handleClick(state) {
+ panel.show({
+ position: button
+ });
+}</pre>
+<p>This wildcard feature does not yet work for the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows"><code>windows</code></a> modules.</p>
+<h3 id="Adding_Listeners_in_Constructors">Adding Listeners in Constructors</h3>
+<p>Event emitters may be modules, as is the case for the <code>ready</code> event above, or they may be objects returned by constructors.</p>
+<p>In the latter case the <code>options</code> object passed to the constructor typically defines properties whose names are the names of supported event types prefixed with "on": for example, "onOpen", "onReady" and so on. Then in the constructor you can assign a listener function to this property as an alternative to calling the object's <code>on()</code> method.</p>
+<p>For example: the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action"><code>ActionButton</code></a> object emits an event when the button is clicked.</p>
+<p>The following add-on creates a button and assigns a listener to the <code>onClick</code> property of the <code>options</code> object supplied to the button's constructor. The listener loads https://developer.mozilla.org/:</p>
+<pre class="brush: js">require("sdk/ui/button/action").ActionButton({
+  id: "visit-mozilla",
+  label: "Visit Mozilla",
+  icon: "./icon-16.png",
+  onClick: function() {
+    require("sdk/tabs").open("https://developer.mozilla.org/");
+  }
+});
+</pre>
+<p>This is exactly equivalent to constructing the button and then calling the button's <code>on()</code> method:</p>
+<pre class="brush: js">var button = require("sdk/ui/button/action").ActionButton({
+  id: "visit-mozilla",
+  label: "Visit Mozilla",
+  icon: "./icon-16.png"
+});
+
+button.on("click", function() {
+  require("sdk/tabs").open("https://developer.mozilla.org/");
+});
+</pre>
+<h2 id="Removing_Event_Listeners">Removing Event Listeners</h2>
+<p>Event listeners can be removed by calling <code>removeListener(type, listener)</code>, supplying the type of event and the listener to remove.</p>
+<p>The listener must have been previously been added using one of the methods described above.</p>
+<p>In the following add-on, we add two listeners to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#ready"><code>tabs</code> module's <code>ready</code> event</a>. One of the handler functions removes the listener again.</p>
+<p>Then we open two tabs.</p>
+<pre class="brush: js">var tabs = require("sdk/tabs");
+
+function listener1() {
+ console.log("Listener 1");
+ tabs.removeListener("ready", listener1);
+}
+
+function listener2() {
+ console.log("Listener 2");
+}
+
+tabs.on("ready", listener1);
+tabs.on("ready", listener2);
+
+tabs.open("https://www.mozilla.org");
+tabs.open("https://www.mozilla.org");
+</pre>
+<p>We should see output like this:</p>
+<pre>info: tabevents: Listener 1
+info: tabevents: Listener 2
+info: tabevents: Listener 2
+</pre>
+<p>Listeners will be removed automatically when the add-on is unloaded.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/base64/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/base64/index.html
new file mode 100644
index 0000000000..bbde3e418f
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/base64/index.html
@@ -0,0 +1,65 @@
+---
+title: base64
+slug: Mozilla/Add-ons/SDK/High-Level_APIs/base64
+translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/base64
+---
+<p>{{AddonSidebar}}</p>
+
+<div class="note">
+<p>不稳定</p>
+</div>
+
+<p>使用Base64算法编码和解码数据</p>
+
+<pre class="brush: js">var base64 = require("sdk/base64");
+
+var encodedData = base64.encode("Hello, World");//"SGVsbG8sIFdvcmxk"
+var decodedData = base64.decode(encodedData);//"Hello, World"</pre>
+
+<h2 id="Globals">Globals</h2>
+
+<h3 id="函数">函数</h3>
+
+<h4 class="addon-sdk-api-name" id="encode(data_charset)"><code>encode(data, charset)</code></h4>
+
+<p>将数据编码成ASCII的Base64字符串。</p>
+
+<h5 id="参数">参数</h5>
+
+<p><strong>data : string</strong><br>
+ 需要被编码的字符串</p>
+
+<p><strong>charset : string</strong><br>
+ 字符串的编码字符集(可选)。唯一能接受的值<code>“UTF-8”</code>。为了进行编码和解码Unicode字符串,需要设置字符集参数:</p>
+
+<pre class="brush: js">var base64 = require("sdk/base64");
+
+var encodedData = base64.encode(unicodeString, "utf-8");
+</pre>
+
+<h5 id="返回">返回</h5>
+
+<p><strong>string</strong> : 编码后的Base64字符串。</p>
+
+<h4 class="addon-sdk-api-name" id="decode(data_charset)"><code>decode(data, charset)</code></h4>
+
+<p>解码一个已使用base-64编码的数据字符串</p>
+
+<h5 id="参数_2">参数</h5>
+
+<p><strong>data : string</strong><br>
+ 需要被解码的字符串</p>
+
+<p><strong>charset : string</strong><br>
+ 字符串的编码字符集(可选)。唯一能接受的值<code>“UTF-8”</code>。为了进行编码和解码Unicode字符串,需要设置字符集参数:</p>
+
+<pre class="brush: js">var base64 = require("sdk/base64");
+
+var decodedData = base64.decode(encodedData, "utf-8");
+</pre>
+
+<h5 id="返回_2">返回</h5>
+
+<p><strong>string</strong> : 解码后的字符串</p>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/clipboard/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/clipboard/index.html
new file mode 100644
index 0000000000..e56a9223cd
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/clipboard/index.html
@@ -0,0 +1,101 @@
+---
+title: clipboard(剪贴板)
+slug: Mozilla/Add-ons/SDK/High-Level_APIs/clipboard
+translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/clipboard
+---
+<p>{{AddonSidebar}}</p>
+
+<div class="note">
+<p>稳定版</p>
+</div>
+
+<p><span class="seoSummary">操作系统剪贴板,设置或获取其内容</span></p>
+
+<h2 id="用法">用法</h2>
+
+<p>你可以选择性地设置将要获取或设置的内容的格式. 支持一下格式:</p>
+
+<ul>
+ <li><code>text</code> (纯文本)</li>
+ <li><code>html</code> (HTML标记语言)</li>
+ <li><code>image</code> (经过base-64编码过的png图片)</li>
+</ul>
+
+<p>如果没有提供格式参数的话,剪贴板模块会自动检测。</p>
+
+<p>现在在Windows操作系统下,"image"格式并不支持透明度。</p>
+
+<h3 id="示例">示例</h3>
+
+<p>设置和获取剪贴板内容。</p>
+
+<pre class="brush: js">var clipboard = require("sdk/clipboard");
+clipboard.set("Lorem ipsum dolor sit amet");
+var contents = clipboard.get();</pre>
+
+<p>将剪贴板内容设置为某些html。</p>
+
+<pre class="brush: js">var clipboard = require("sdk/clipboard");
+clipboard.set("&lt;blink&gt;Lorem ipsum dolor sit amet&lt;/blink&gt;", "html");</pre>
+
+<p>如果剪贴板内容中包含有html,则将其在新标签页中打开。</p>
+
+<pre class="brush: js">var clipboard = require("sdk/clipboard");
+if (clipboard.currentFlavors.indexOf("html") != -1)
+ require("sdk/tabs").open("data:text/html;charset=utf-8," + clipboard.get("html"));</pre>
+
+<p>将剪贴板内容设置为一幅图片。</p>
+
+<pre class="brush: js">var clipboard = require("sdk/clipboard");
+clipboard.set("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" +
+ "AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" +
+ "N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" +
+ "bWRR9AAAAABJRU5ErkJggg%3D%3D");</pre>
+
+<p>如果剪贴板内容中包含图片,则将其在新标签页中打开。</p>
+
+<pre class="brush: js">var clipboard = require("sdk/clipboard");
+if (clipboard.currentFlavors.indexOf("image") != -1)
+ require("sdk/tabs").open(clipboard.get());</pre>
+
+<p>如前所述,图片的参数类型很容易被忽略,例如在网页中选中复制一张图片,得到的格式会是html而不是所预期的image。如果你是想将剪贴板的内容设置成像data URL这样的文本字符串而不是图片的话,可以通过将格式设置为text实现。</p>
+
+<pre class="brush: js">var clipboard = require("sdk/clipboard");
+
+clipboard.set("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYA" +
+ "AABzenr0AAAASUlEQVRYhe3O0QkAIAwD0eyqe3Q993AQ3cBSUKpygfsNTy" +
+ "N5ugbQpK0BAADgP0BRDWXWlwEAAAAAgPsA3rzDaAAAAHgPcGrpgAnzQ2FG" +
+ "bWRR9AAAAABJRU5ErkJggg%3D%3D", "text");</pre>
+
+<h2 id="Globals">Globals</h2>
+
+<h3 id="函数">函数</h3>
+
+<h4 class="addon-sdk-api-name" id="set(data_datatype)"><code>set(data, datatype)</code></h4>
+
+<p>将用户剪贴板上的内容用data替换。</p>
+
+<h5 id="参数">参数</h5>
+
+<p><strong>data : string</strong><br>
+ 要放入剪贴板的内容。</p>
+
+<p><strong>datatype : string</strong><br>
+ 内容的格式 ,为"text"或"html" 或 "image"。可选参数.</p>
+
+<h4 class="addon-sdk-api-name" id="get(datatype)"><code>get(datatype)</code></h4>
+
+<p>获取用户当前剪贴板的内容。</p>
+
+<h5 id="参数_2">参数</h5>
+
+<p><strong>datatype : string</strong><br>
+ 只有当剪贴板中的内容格式为datatype指定的格式时才获取 (可选).。当剪贴板中的内容非所提供的datatype指定的格式时,函数回返回null。</p>
+
+<h3 id="属性">属性</h3>
+
+<h4 class="addon-sdk-api-name" id="currentFlavors"><code>currentFlavors</code></h4>
+
+<p>剪贴板上的内容有时会是多种格式。例如,HTML内容即能匹配HTML格式(html),又能匹配纯文本格式(text)。这个属性为一个数组,数组中的元素是剪贴板内容所匹配的所有格式,如["text","html"]。</p>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/index.html
new file mode 100644
index 0000000000..d0d7bd569a
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/index.html
@@ -0,0 +1,12 @@
+---
+title: High-Level APIs
+slug: Mozilla/Add-ons/SDK/High-Level_APIs
+translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs
+---
+<p>{{AddonSidebar}}</p>
+
+<p>此页面列出的模块使用的是高级的API:创建用户界面,与网络进行交互并与浏览器交互。</p>
+
+<p>除非文件明确说明,否则这些API是稳定的,我们避免做出不兼容的改变。
+
+{{ LandingPageListSubpages ("/en-US/Add-ons/SDK/High-Level_APIs", 5) }}</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/notifications/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/notifications/index.html
new file mode 100644
index 0000000000..415450dca7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/notifications/index.html
@@ -0,0 +1,129 @@
+---
+title: notifications(通知)
+slug: Mozilla/Add-ons/SDK/High-Level_APIs/notifications
+tags:
+ - Add-on SDK
+ - 通知
+translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/notifications
+---
+<p>{{AddonSidebar}}</p>
+
+<div class="note">
+<p>Stable</p>
+</div>
+
+<p><span class="seoSummary">向用户展示短暂的 <a href="http://en.wikipedia.org/wiki/Toast_%28computing%29">toaster</a> 风格的桌面消息。</span></p>
+
+<h2 id="用法">用法</h2>
+
+<p>本 API 支持Windows、使用<a href="http://growl.info/">Growl</a>(或者像OS X 10.9 Mavericks那样的通知中心)的 OS X 的桌面通知,以及使用 libnotify 的Linux系统</p>
+
+<p>这儿有个典型的例子。当消息被点击,控制台上回记录一个字符串。</p>
+
+<pre class="brush: js">var notifications = require("sdk/notifications");
+notifications.notify({
+ title: "Jabberwocky",
+ text: "'Twas brillig, and the slithy toves",
+ data: "did gyre and gimble in the wabe",
+ onClick: function (data) {
+ console.log(data);
+ // console.log(this.data) would produce the same result.
+ }
+});
+</pre>
+
+<p>下面这个示例用来展示一个保存在 add-on 的 <code>data</code> 目录下的图标。参看 <a href="/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code></a> 模块文档以获取更多信息。</p>
+
+<pre class="brush: js">var notifications = require("sdk/notifications");
+var self = require("sdk/self");
+var myIconURL = self.data.url("myIcon.png");
+
+notifications.notify({
+ text: "I have an icon!",
+ iconURL: myIconURL
+});</pre>
+
+<div class="note">
+<p>从 Firefox 34 起,你能使用 <code>"./myIcon.png"</code> 作为 <code>self.data.url("myIcon.png")</code> 的别名。所以你也可以把上面的代码重写成这样:</p>
+
+<pre class="brush: js">var notifications = require("sdk/notifications");
+var myIconURL = "./myIcon.png";
+
+notifications.notify({
+ text: "I have an icon!",
+ iconURL: myIconURL
+});</pre>
+</div>
+
+<p>本模块依赖于底层系统的通知服务。如果用户的系统不支持桌面通知或者通知服务没有运行:</p>
+
+<ul>
+ <li>如果 Firefox 正常运行,通知会记录在 Firefox 的错误控制台</li>
+ <li>如果用户从命令行启动 Firefox,通知会记录到终端。</li>
+</ul>
+
+<h2 id="Globals">Globals</h2>
+
+<h3 id="函数">函数</h3>
+
+<h4 class="addon-sdk-api-name" id="notify(options)"><code>notify(options)</code></h4>
+
+<p>向用户展示一个短暂的通知</p>
+
+<h5 id="参数">参数</h5>
+
+<p><strong>options : object</strong><br>
+ 可选项:</p>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>title</td>
+ <td>string</td>
+ <td>
+ <p>作为消息标题的字符串。</p>
+ </td>
+ </tr>
+ <tr>
+ <td>text</td>
+ <td>作为消息体的字符串。</td>
+ <td>
+ <p> </p>
+ </td>
+ </tr>
+ <tr>
+ <td>iconURL</td>
+ <td>string</td>
+ <td>
+ <p>消息里的图标的 URL 。可以是个远程的、本地的或者使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code></a> 模块的 URL。</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onClick</td>
+ <td>function</td>
+ <td>
+ <p>用户点击消息是调用的函数。它会传递一个 <code>data</code> 值。</p>
+ </td>
+ </tr>
+ <tr>
+ <td>data</td>
+ <td>string</td>
+ <td>
+ <p>传递给 <code>onClick</code> 的字符串。</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/panel/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/panel/index.html
new file mode 100644
index 0000000000..3a86fb0c61
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/panel/index.html
@@ -0,0 +1,899 @@
+---
+title: panel
+slug: Mozilla/Add-ons/SDK/High-Level_APIs/panel
+translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/panel
+---
+<div class="note">
+<p>稳定版本</p>
+</div>
+
+<p><span class="seoSummary">创建临时的 add-on's 用户界面对话框.</span></p>
+
+<h2 id="用法">用法</h2>
+
+<p>该模块导出了一个单独的构造函数函数 <code>Panel()</code> 构建一个Panel对话框 .</p>
+
+<p>面板是一个对话框。其内容是指定的HTML,你可以在它执行脚本,所以面板的外观和行为是有限的只有你可以使用HTML,CSS,JavaScript。</p>
+
+<p>下面的截图显示了一个面板,其内容是从当前打开的选项卡的列表中构建的:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6595/panel-tabs-osx.png" style="display: block; height: 238px; margin-left: auto; margin-right: auto; width: 307px;"></p>
+
+<p>面板是呈现临时用户界面中容易忽视和解聘的用户比模态对话框的方式,是有用的,因为面板隐藏瞬间用户交互部分的应用程序接口外。</p>
+
+<p><br>
+ 面板的内容加载快作为它是创建,面板显示之前,和内容仍然加载时面板是隐藏的,所以它是可能保持面板周围的背景,更新其内容适当地准备下一次显示。</p>
+
+<p><br>
+ 您的插件可以接收通知,当面板显示或隐藏通过听其显示和隐藏事件。<br>
+ 打开面板将关闭已打开的面板。</p>
+
+<h3 id="Panel_内容">Panel 内容</h3>
+
+<p>该面板的内容指定为HTML,它是在contenturl选项面板的构造函数提供的URL加载。</p>
+
+<p><br>
+ 你可以加载远程HTML到面板:</p>
+
+<pre class="brush: js">var panel = require("sdk/panel").Panel({
+ width: 180,
+ height: 180,
+ contentURL: "https://en.wikipedia.org/w/index.php?title=Jetpack&amp;useformat=mobile"
+});
+
+panel.show();</pre>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6597/wikipedia-jetpack-panel.png" style="display: block; height: 411px; margin-left: auto; margin-right: auto; width: 494px;"></p>
+
+<p>你也可以加载HTML已经打包你的 add-on,这可能是你将如何创建对话框。要做到这一点,在你的 add-on 的 <em><strong>data </strong></em>目录中保存的HTML 和加载使用 <strong><em><code>data.url()</code></em></strong>方法,由 <em><strong><a href="/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code></a></strong></em> 模块导出, 像下面:</p>
+
+<pre class="brush: js">var panel = require("sdk/panel").Panel({
+ contentURL: require("sdk/self").data.url("myFile.html")
+});
+
+panel.show();</pre>
+
+<div class="note">
+<p>从Firefox 34以后, 你可以使用 <code>"./myFile.html" 作为</code><code>self.data.url("myFile.html")</code> 的<code>别名</code>. 所以你可以重写成下面的示例:</p>
+
+<pre class="brush: js">var panel = require("sdk/panel").Panel({
+ contentURL: "./myFile.html"
+});
+
+panel.show();
+</pre>
+</div>
+
+<h3 id="Panel_positioning">Panel positioning</h3>
+
+<p>By default the panel appears in the center of the currently active browser window. You can position the panel by passing a <code>position</code> to the panel's <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#Panel(options)">constructor</a> or to its <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#show(options)"><code>show()</code></a> method.</p>
+
+<h3 id="Attaching_panels_to_buttons">Attaching panels to buttons</h3>
+
+<p>You can attach a panel to a <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">toggle button</a> by passing the button itself as the <code>position</code> option to the panel's <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#show(options)"><code>show()</code></a> method or to its constructor:</p>
+
+<pre class="brush: js">var { ToggleButton } = require('sdk/ui/button/toggle');
+var panels = require("sdk/panel");
+var self = require("sdk/self");
+
+var button = ToggleButton({
+  id: "my-button",
+  label: "my button",
+  icon: {
+    "16": "./icon-16.png",
+    "32": "./icon-32.png",
+    "64": "./icon-64.png"
+  },
+  onChange: handleChange
+});
+
+var panel = panels.Panel({
+  contentURL: self.data.url("panel.html"),
+  onHide: handleHide
+});
+
+function handleChange(state) {
+  if (state.checked) {
+    panel.show({
+      position: button
+    });
+  }
+}
+
+function handleHide() {
+  button.state('window', {checked: false});
+}</pre>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/7615/panel-button.png" style="display: block; height: 332px; margin-left: auto; margin-right: auto; width: 397px;"></p>
+
+<h3 id="Updating_panel_content">Updating panel content</h3>
+
+<p>You can update the panel's content by:</p>
+
+<ul>
+ <li>sending a message to a content script that updates the DOM in the same document. This is usually the best approach.</li>
+ <li>embedding an <a href="/en-US/docs/Web/HTML/Element/iframe">iframe</a> in the panel, and changing its document</li>
+ <li>setting the panel's <code>contentURL</code> property. However, doing this will cause any content scripts to be unloaded and then reloaded, so it may be less efficient, and you'll lose any state associated with the scripts.</li>
+</ul>
+
+<h3 id="Scripting_panel_content">Scripting panel content</h3>
+
+<p>You can't directly access your panel's content from your main add-on code. To access the panel's content, you need to load a script into the panel. In the SDK these scripts are called "content scripts" because they're explicitly used for interacting with web content.</p>
+
+<p>While content scripts can access the content they're attached to, they can't use the SDK's APIs. So implementing a complete solution usually means you have to send messages between the content script and the main add-on code.</p>
+
+<ul>
+ <li>
+ <p>You can specify one or more content scripts to load into a panel using the <code>contentScript</code> or <code>contentScriptFile</code> options to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#Panel(options)"><code>Panel()</code> constructor</a>.</p>
+ </li>
+ <li>
+ <p>You can communicate with the script using either the <a href="/en-US/Add-ons/SDK/Guides/using_postMessage"><code>postMessage()</code></a> API or (preferably, usually) the <a href="/en-US/Add-ons/SDK/Guides/using_port"><code>port</code></a> API.</p>
+ </li>
+</ul>
+
+<p>For example, here's an add-on whose content script intercepts mouse clicks on links inside the panel, and sends the target URL to the main add-on code. The content script sends messages using <code>self.port.emit()</code> and the add-on script receives them using <code>panel.port.on()</code>.</p>
+
+<pre class="brush: js">var myScript = "window.addEventListener('click', function(event) {" +
+ " var t = event.target;" +
+ " if (t.nodeName == 'A')" +
+ " self.port.emit('click-link', t.toString());" +
+ "}, false);"
+
+var panel = require("sdk/panel").Panel({
+ contentURL: "http://www.bbc.co.uk/mobile/index.html",
+ contentScript: myScript
+});
+
+panel.port.on("click-link", function(url) {
+ console.log(url);
+});
+
+panel.show();</pre>
+
+<p>This example uses <code>contentScript</code> to supply the script as a string. It's usually better practice to use <code>contentScriptFile</code>, which is a URL pointing to a script file saved under your add-on's <code>data</code> directory.</p>
+
+<div class="warning">
+<p><strong>Warning:</strong> Unless your content script is extremely simple and consists only of a static string, don't use <code>contentScript</code>: if you do, you may have problems getting your add-on approved on AMO.</p>
+
+<p>Instead, keep the script in a separate file and load it using <code>contentScriptFile</code>. This makes your code easier to maintain, secure, debug and review.</p>
+</div>
+
+<h3 id="Getting_user_input">Getting user input</h3>
+
+<div class="note">
+<p><strong>Note:</strong> This example uses the <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> API, which is only available from Firefox 29 onwards.</p>
+</div>
+
+<p>The following add-on adds a button which displays a panel when clicked. The panel just contains a {{HTMLElement("textarea")}} element: when the user presses the <code>return</code> key, the contents of the <code>&lt;textarea&gt;</code> is sent to the main add-on code.</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/7647/panel.png" style="display: block; margin-left: auto; margin-right: auto;"></p>
+
+<p>The add-on consists of six files:</p>
+
+<ul>
+ <li><code>main.js</code>: the main add-on code, that creates the button and panel</li>
+ <li><code>get-text.js</code>: the content script that interacts with the panel content</li>
+ <li><code>text-entry.html</code>: the panel content itself, specified as HTML</li>
+ <li><code>icon-16.png</code>, <code>icon-32.png</code>, and <code>icon-64.png</code>: icons for the button in three different sizes</li>
+</ul>
+
+<p>"main.js" is saved in your add-on's <code>lib</code> directory, and the other files go in your add-on's <code>data</code> directory:</p>
+
+<pre>my-addon/
+ data/
+ get-text.js
+ icon-16.png
+ icon-32.png
+ icon-64.png
+ text-entry.html
+ lib/
+ main.js
+</pre>
+
+<p>The "main.js" looks like this:</p>
+
+<pre class="brush: js">var data = require("sdk/self").data;
+// Construct a panel, loading its content from the "text-entry.html"
+// file in the "data" directory, and loading the "get-text.js" script
+// into it.
+var text_entry = require("sdk/panel").Panel({
+  contentURL: data.url("text-entry.html"),
+  contentScriptFile: data.url("get-text.js")
+});
+
+// Create a button
+require("sdk/ui/button/action").ActionButton({
+  id: "show-panel",
+  label: "Show Panel",
+  icon: {
+    "16": "./icon-16.png",
+    "32": "./icon-32.png",
+    "64": "./icon-64.png"
+  },
+  onClick: handleClick
+});
+
+// Show the panel when the user clicks the button.
+function handleClick(state) {
+  text_entry.show();
+}
+
+// When the panel is displayed it generated an event called
+// "show": we will listen for that event and when it happens,
+// send our own "show" event to the panel's script, so the
+// script can prepare the panel for display.
+text_entry.on("show", function() {
+  text_entry.port.emit("show");
+});
+
+// Listen for messages called "text-entered" coming from
+// the content script. The message payload is the text the user
+// entered.
+// In this implementation we'll just log the text to the console.
+text_entry.port.on("text-entered", function (text) {
+  console.log(text);
+  text_entry.hide();
+});</pre>
+
+<p>The content script "get-text.js" looks like this:</p>
+
+<pre class="brush: js">// When the user hits return, send the "text-entered"
+// message to main.js.
+// The message payload is the contents of the edit box.
+var textArea = document.getElementById("edit-box");
+textArea.addEventListener('keyup', function onkeyup(event) {
+ if (event.keyCode == 13) {
+ // Remove the newline.
+ text = textArea.value.replace(/(\r\n|\n|\r)/gm,"");
+ self.port.emit("text-entered", text);
+ textArea.value = '';
+ }
+}, false);
+// Listen for the "show" event being sent from the
+// main add-on code. It means that the panel's about
+// to be shown.
+//
+// Set the focus to the text area so the user can
+// just start typing.
+self.port.on("show", function onShow() {
+ textArea.focus();
+});</pre>
+
+<p>Finally, the "text-entry.html" file defines the <code>&lt;textarea&gt;</code> element:<code> </code></p>
+
+<pre class="brush: html">&lt;html&gt;
+&lt;head&gt;
+    &lt;style type="text/css" media="all"&gt;
+      textarea {
+        margin: 10px;
+      }
+      body {
+        background-color: gray;
+      }
+    &lt;/style&gt;
+  &lt;/head&gt;
+&lt;body&gt;
+    &lt;textarea rows="13" cols="33" id="edit-box"&gt;&lt;/textarea&gt;
+  &lt;/body&gt;
+&lt;/html&gt;</pre>
+
+<p>Finally, save these three icon files to the "data" directory:</p>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="height: 16px; width: 16px;"></td>
+ <td>icon-16.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="height: 32px; width: 32px;"></td>
+ <td>icon-32.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="height: 64px; width: 64px;"></td>
+ <td>icon-64.png</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>To learn much more about content scripts, see the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> guide.</p>
+
+<h3 id="Scripting_trusted_panel_content">Scripting trusted panel content</h3>
+
+<div class="note">
+<p><strong>Note:</strong> This example uses the <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> API, which is only available from Firefox 29 onwards.</p>
+</div>
+
+<p>We've already seen that you can package HTML files in your add-on's <code>data</code> directory and use them to define the panel's content. We can call this "trusted" content, because unlike content loaded from a source outside the add-on, the add-on author knows exactly what it's doing. To interact with trusted content you don't need to use content scripts: you can just include a script from the HTML file in the normal way, using <code>script</code> tags.</p>
+
+<p>Like a content script, these scripts can communicate with the add-on code using the <a href="/en-US/Add-ons/SDK/Guides/using_postMessage"><code>postMessage()</code></a> API or the <a href="/en-US/Add-ons/SDK/Guides/using_port"><code>port</code></a> API. The crucial difference is that these scripts access the <code>postMessage</code> and <code>port</code> objects through the <code>addon</code> object, whereas content scripts access them through the <code>self</code> object.</p>
+
+<p>To show the difference, we can easily convert the <code>text-entry</code> add-on above to use normal page scripts instead of content scripts.</p>
+
+<p>The main add-on code is exactly the same as the main add-on code in the previous example, except that we don't attach a content script:</p>
+
+<pre class="brush: js">var data = require("sdk/self").data;
+// Construct a panel, loading its content from the "text-entry.html"
+// file in the "data" directory, and loading the "get-text.js" script
+// into it.
+var text_entry = require("sdk/panel").Panel({
+  contentURL: data.url("text-entry.html")
+});
+
+// Create a button
+require("sdk/ui/button/action").ActionButton({
+  id: "show-panel",
+  label: "Show Panel",
+  icon: {
+    "16": "./icon-16.png",
+    "32": "./icon-32.png",
+    "64": "./icon-64.png"
+  },
+  onClick: handleClick
+});
+
+// Show the panel when the user clicks the button.
+function handleClick(state) {
+  text_entry.show();
+}
+
+// When the panel is displayed it generated an event called
+// "show": we will listen for that event and when it happens,
+// send our own "show" event to the panel's script, so the
+// script can prepare the panel for display.
+text_entry.on("show", function() {
+  text_entry.port.emit("show");
+});
+
+// Listen for messages called "text-entered" coming from
+// the content script. The message payload is the text the user
+// entered.
+// In this implementation we'll just log the text to the console.
+text_entry.port.on("text-entered", function (text) {
+  console.log(text);
+  text_entry.hide();
+});</pre>
+
+<p>The page script is exactly the same as the content script above, except that instead of <code>self</code>, we use <code>addon</code> to access the messaging APIs:</p>
+
+<pre class="brush: js">// When the user hits return, send the "text-entered"
+// message to main.js.
+// The message payload is the contents of the edit box.
+var textArea = document.getElementById("edit-box");
+textArea.addEventListener('keyup', function onkeyup(event) {
+  if (event.keyCode == 13) {
+    // Remove the newline.
+    text = textArea.value.replace(/(\r\n|\n|\r)/gm,"");
+    addon.port.emit("text-entered", text);
+    textArea.value = '';
+  }
+}, false);
+// Listen for the "show" event being sent from the
+// main add-on code. It means that the panel's about
+// to be shown.
+//
+// Set the focus to the text area so the user can
+// just start typing.
+addon.port.on("show", function onShow() {
+  textArea.focus();
+});</pre>
+
+<p>Finally, the HTML file now references "get-text.js" inside a {{HTMLElement("script")}} tag:</p>
+
+<pre class="brush: html">&lt;html&gt;
+&lt;head&gt;
+    &lt;style type="text/css" media="all"&gt;
+      textarea {
+        margin: 10px;
+      }
+      body {
+        background-color: gray;
+      }
+    &lt;/style&gt;
+  &lt;/head&gt;
+  &lt;body&gt;
+ &lt;script src="get-text.js"&gt;&lt;/script&gt;
+    &lt;textarea rows="13" cols="33" id="edit-box"&gt;&lt;/textarea&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
+</pre>
+
+<h3 id="Styling_panel_content">Styling panel content</h3>
+
+<p>The panel's default style is different for each operating system:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/8001/panel-styles-os.png" style="display: block; margin-left: auto; margin-right: auto;">This helps to ensure that the panel's style is consistent with the dialogs displayed by Firefox and other applications, but means you need to take care when applying your own styles.</p>
+
+<p>If the panel's content is packaged along with your add-on and specified using an HTML file in your <code>data</code> directory, you can style it by embedding CSS directly in the HTML file or by referencing a CSS file stored under <code>data</code>:</p>
+
+<pre class="brush: html">&lt;!DOCTYPE HTML&gt;
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;link href="panel-style.css" type="text/css" rel="stylesheet"&gt;
+ &lt;/head&gt;
+ &lt;body&gt;
+ My panel content
+ &lt;/body&gt;
+&lt;/html&gt;</pre>
+
+<p>From Firefox 31 onwards, you can style panel content using the <code>contentStyle</code> or <code>contentStyleFile</code> options. You can use these options even if the panel content is not packaged along with the add-on:</p>
+
+<pre class="brush: js">var panel = require("sdk/panel").Panel({
+ contentURL: "https://en.wikipedia.org/w/index.php?title=Jetpack&amp;useformat=mobile",
+ contentStyle: "body { border: 3px solid blue; }"
+});
+
+panel.show();</pre>
+
+<pre class="brush: js">var self = require("sdk/self");
+
+var panel = require("sdk/panel").Panel({
+ contentURL: "https://en.wikipedia.org/w/index.php?title=Jetpack&amp;useformat=mobile",
+ contentStyleFile: self.data.url("panel-style.css")
+});
+
+panel.show();</pre>
+
+<h3 id="Private_browsing">Private browsing</h3>
+
+<p>If your add-on has not <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing">opted into private browsing</a>, and it calls <code>panel.show()</code> when the currently active window is a <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing#Per-window_private_browsing">private window</a>, then the panel will not be shown.</p>
+
+<h3 id="Panel_limitations">Panel limitations</h3>
+
+<p>Although panels can host HTML documents, they are not implemented as browser tabs, so many things that work in normal web pages do not work inside panels:</p>
+
+<ul>
+ <li>Prior to Firefox 33, you don't get a context menu. From Firefox 33 you can enable a context menu by passing <code>contextMenu: true</code> to the panel's constructor.</li>
+ <li>The HTML {{HTMLElement("select")}} element doesn't work.</li>
+ <li>The HTML {{HTMLElement("datalist")}} element doesn't give you autocomplete suggestions (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=918600">bug 918600</a>).</li>
+ <li>You can't embed Flash (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=952578">bug 952578</a>).</li>
+ <li>You can't provide tooltips using <a href="/en-US/docs/Web/HTML/Global_attributes#attr-title"><code>title</code> attributes</a> (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=918600">bug 918600</a>).</li>
+ <li>Security warning pages (the <a href="https://support.mozilla.org/en-US/kb/connection-untrusted-error-message">"This Connection is Untrusted" warning</a>) does not work, so panels which trigger it will be broken (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1031554">bug 1031554</a>).</li>
+ <li>Mouse button shortcuts, such as using the middle button to open a link in a new page, don't work.</li>
+ <li>Scrolling using keyboard doesn't work properly (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1001914">bug 1001914</a>)</li>
+</ul>
+
+<h2 id="Globals">Globals</h2>
+
+<h3 id="Constructors">Constructors</h3>
+
+<h4 class="addon-sdk-api-name" id="Panel(options)"><code>Panel(options)</code></h4>
+
+<p>Creates a panel.</p>
+
+<h5 id="Parameters">Parameters</h5>
+
+<p><strong>options : object</strong><br>
+ Optional options:</p>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>width</code></td>
+ <td>number</td>
+ <td>
+ <p>The width of the panel in pixels. Optional.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>height</code></td>
+ <td>number</td>
+ <td>
+ <p>The height of the panel in pixels. Optional.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>position</code></td>
+ <td>
+ <p>object, button, widget</p>
+ </td>
+ <td>
+ <p>The position of the panel. Ignored if the panel is opened by a widget.</p>
+
+ <p>This may be one of three things:</p>
+
+ <ul>
+ <li>a <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">toggle button</a>. If this is supplied the panel will be shown attached to the button. See the section on <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#Attaching_panels_to_buttons">attaching panels to buttons</a>.</li>
+ <li>a <a href="/en-US/Add-ons/SDK/High-Level_APIs/widget">widget</a> object. If this is supplied the panel will be shown attached to the widget.</li>
+ <li>an object which specifies where in the window the panel should be shown. The rest of this section describes this object.</li>
+ </ul>
+
+ <p>The position object has one or more of the following properties: <code>top</code>, <code>right</code>, <code>bottom</code> and <code>left</code>. Their values are expressed in pixels. Any other properties will be ignored.</p>
+
+ <p>The default alignment along each axis is centered: so to display a panel centred along the vertical or horizontal axis, just omit that axis:</p>
+
+ <pre class="brush: js">
+// Show the panel centered horizontally and
+// aligned to the bottom of the content area
+require("sdk/panel").Panel({
+ position: {
+ bottom: 0
+ }
+}).show();
+
+// Show the panel centered vertically and
+// aligned to the left of the content area
+require("sdk/panel").Panel({
+ position: {
+ left: 0
+ }
+}).show();
+
+// Centered panel, default behavior
+require("sdk/panel").Panel({}).show();</pre>
+
+ <p>As with the CSS <code>top</code>, <code>bottom</code>, <code>left</code>, and <code>right</code> properties, setting both <code>top</code> and <code>bottom</code> or both <code>left</code> and <code>right</code> will implicitly set the panel's <code>height</code> or <code>width</code> relative to the content window:</p>
+
+ <pre class="brush: js">
+// Show the panel centered horizontally, with:
+// - the top edge 40px from the top
+// of the content window
+// - the bottom edge 100px from the bottom
+// of the content window
+require("sdk/panel").Panel({
+ position: {
+ top: 40,
+ bottom: 100
+ }
+}).show();</pre>
+
+ <p>If you set both <code>top</code> and <code>bottom</code>, but also set the panel's height explicitly using the <code>height</code> property, then the panel will ignore <code>bottom</code>, just as CSS does for its properties with the same name:</p>
+
+ <pre class="brush: js">
+// Show the panel centered horizontally, with:
+// - the top edge 40px from the top
+// of the content window
+// - a height of 400px
+require("sdk/panel").Panel({
+ position: {
+ top: 40,
+ bottom: 100,
+ },
+ height: 400
+}).show();
+
+// This is equivalent to:
+
+require("panel").Panel({
+ position {
+ top: 40
+ },
+ height: 400
+}).show();</pre>
+
+ <p>The same principle is applied in the horizontal axis with <code>width</code>, <code>left</code> and <code>right</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>focus</code></td>
+ <td>boolean</td>
+ <td>
+ <p>Set to <code>false</code> to prevent taking the focus away when the panel is shown. Only turn this off if necessary, to prevent accessibility issue. Optional, default to <code>true</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>contentURL</code></td>
+ <td>string,URL</td>
+ <td>
+ <p>The URL of the content to load in the panel. That is, they can't refer to remote scripts. The URLs are usually constructed using <a href="/en-US/Add-ons/SDK/High-Level_APIs/self#data.url(name)"><code>self.data.url()</code></a>.</p>
+
+ <div class="note">
+ <p>From Firefox 34, you can use <code>"./my-file.html"</code> as an alias for <code>self.data.url("my-<code>file.html</code>")</code>.</p>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td><code>allow</code></td>
+ <td>object</td>
+ <td>
+ <p>An optional object describing permissions for the content. It should contain a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content. <code>script</code> defaults to true.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>contentScriptFile</code></td>
+ <td>string,array</td>
+ <td>
+ <p>A URL or an array of URLs. The URLs point to scripts to load into the panel.</p>
+
+ <p>The scripts must be packaged with the add-on under the add-on's <code>data</code> directory. That is, they can't refer to remote scripts. The URLs are usually constructed using <a href="/en-US/Add-ons/SDK/High-Level_APIs/self#data.url(name)"><code>self.data.url()</code></a>.</p>
+
+ <div class="note">
+ <p>From Firefox 34, you can use <code>"./my-script.js"</code> as an alias for <code>self.data.url("my-script.js")</code>.</p>
+ </div>
+
+ <p>Content scripts specified by this property are loaded <em>before</em> those specified by the <code>contentScript</code> property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>contentScript</code></td>
+ <td>string,array</td>
+ <td>
+ <p>A string or an array of strings containing the texts of content scripts to load. Content scripts specified by this property are loaded <em>after</em> those specified by the <code>contentScriptFile</code> property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>contentStyleFile</code></td>
+ <td>string, array</td>
+ <td>
+ <p>A URL or an array of URLs. The URLs point to CSS stylesheets to load into the panel.</p>
+
+ <p>The stylesheets must be packaged with the add-on under the add-on's <code>data</code> directory. That is, they can't refer to remote stylesheets. The URLs are usually constructed using <a href="/en-US/Add-ons/SDK/High-Level_APIs/self#data.url(name)"><code>self.data.url()</code></a>.</p>
+
+ <p>Stylesheets specified by this property are loaded <em>before</em> those specified by the <code>contentStyle</code> property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>contentStyle</code></td>
+ <td>string, array</td>
+ <td>
+ <p>A string or an array of strings containing the texts of stylesheets to load. Stylesheets specified by this property are loaded <em>after</em> those specified by the <code>contentStyleFile</code> property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>contentScriptWhen</code></td>
+ <td>string</td>
+ <td>
+ <p>When to load the content scripts. This may take one of the following values:</p>
+
+ <ul>
+ <li>"start": load content scripts immediately after the document element for the panel is inserted into the DOM, but before the DOM content itself has been loaded</li>
+ <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li>
+ <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the panel has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li>
+ </ul>
+
+ <p>This property is optional and defaults to "end".</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>contentScriptOptions</code></td>
+ <td>object</td>
+ <td>
+ <p>Read-only value exposed to content scripts under <code>addon.options</code> property.</p>
+
+ <p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>contextMenu</code></td>
+ <td>boolean</td>
+ <td>
+ <div class="geckoVersionNote">
+ <p>New in Firefox 33</p>
+ </div>
+
+ <p>Whether to show a context menu when the user context-clicks in the panel. The context menu will be the same one that's displayed in web pages. Optional, defaults to <code>false</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>onMessage</code></td>
+ <td>function</td>
+ <td>
+ <p>Include this to listen to the panel's <code>message</code> event.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>onShow</code></td>
+ <td>function</td>
+ <td>
+ <p>Include this to listen to the panel's <code>show</code> event.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>onHide</code></td>
+ <td>function</td>
+ <td>
+ <p>Include this to listen to the panel's <code>hide</code> event.</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Panel">Panel</h2>
+
+<p>The Panel object represents a floating modal dialog that can by an add-on to present user interface content.</p>
+
+<p>Once a panel object has been created it can be shown and hidden using its <code>show()</code> and <code>hide()</code> methods. Once a panel is no longer needed it can be deactivated using <code>destroy()</code>.</p>
+
+<p>The content of a panel is specified using the <code>contentURL</code> option. An add-on can interact with the content of a panel using content scripts which it supplies in the <code>contentScript</code> and/or <code>contentScriptFile</code> options. For example, a content script could create a menu and send the user's selection to the add-on.</p>
+
+<h3 id="Methods">Methods</h3>
+
+<h4 class="addon-sdk-api-name" id="destroy()"><code>destroy()</code></h4>
+
+<p>Destroys the panel, unloading any content that was loaded in it. Once destroyed, the panel can no longer be used. If you just want to hide the panel and might show it later, use <code>hide</code> instead.</p>
+
+<h4 class="addon-sdk-api-name" id="postMessage(message)"><code>postMessage(message)</code></h4>
+
+<p>Sends a message to the content scripts.</p>
+
+<h5 id="Parameters_2">Parameters</h5>
+
+<p><strong>message : value</strong><br>
+ The message to send. Must be stringifiable to JSON.</p>
+
+<h4 class="addon-sdk-api-name" id="show(options)"><code>show(options)</code></h4>
+
+<p>Displays the panel.</p>
+
+<p>If the <code>options</code> argument is given, it will be shallow merged with the options provided in the constructor: the <code>options</code> passed in the <code>show</code> method takes precedence.</p>
+
+<p>Passing options here is useful for making temporary changes without touching the default values.</p>
+
+<h5 id="Parameters_3">Parameters</h5>
+
+<p><strong>options : object</strong><br>
+ Optional options:</p>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>width</td>
+ <td>number</td>
+ <td>
+ <p>The width of the panel in pixels. Optional.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>height</td>
+ <td>number</td>
+ <td>
+ <p>The height of the panel in pixels. Optional.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>position</td>
+ <td>object</td>
+ <td>
+ <p>The position of the panel. Optional. See <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel#Panel(options)">Panel's options</a> for further details.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>focus</td>
+ <td>boolean</td>
+ <td>
+ <p>Set to <code>false</code> to prevent taking the focus away when the panel is shown.</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h4 class="addon-sdk-api-name" id="hide()"><code>hide()</code></h4>
+
+<p>Stops displaying the panel.</p>
+
+<h4 class="addon-sdk-api-name" id="resize(width_height)"><code>resize(width, height)</code></h4>
+
+<p>Resizes the panel.</p>
+
+<h5 id="Parameters_4">Parameters</h5>
+
+<p><strong>width : number</strong><br>
+ The new width of the panel in pixels.</p>
+
+<p><strong>height : number</strong><br>
+ The new height of the panel in pixels.</p>
+
+<h4 class="addon-sdk-api-name" id="on(type_listener)"><code>on(type, listener)</code></h4>
+
+<p>Registers an event listener with the panel.</p>
+
+<h5 id="Parameters_5">Parameters</h5>
+
+<p><strong>type : string</strong><br>
+ The type of event to listen for.</p>
+
+<p><strong>listener : function</strong><br>
+ The listener function that handles the event.</p>
+
+<h4 class="addon-sdk-api-name" id="removeListener(type_listener)"><code>removeListener(type, listener)</code></h4>
+
+<p>Unregisters an event listener from the panel.</p>
+
+<h5 id="Parameters_6">Parameters</h5>
+
+<p><strong>type : string</strong><br>
+ The type of event for which <code>listener</code> was registered.</p>
+
+<p><strong>listener : function</strong><br>
+ The listener function that was registered.</p>
+
+<h3 id="Properties">Properties</h3>
+
+<h4 class="addon-sdk-api-name" id="port"><code>port</code></h4>
+
+<p>EventEmitter object that allows you to:</p>
+
+<ul>
+ <li>send events to the content script using the <code>port.emit</code> function</li>
+ <li>receive events from the content script using the <code>port.on</code> function</li>
+</ul>
+
+<p>See the guide to <a href="/en-US/Add-ons/SDK/Guides/using_port"> communicating using <code>port</code></a> for details.</p>
+
+<h4 class="addon-sdk-api-name" id="isShowing"><code>isShowing</code></h4>
+
+<p>Tells if the panel is currently shown or not. This property is read-only.</p>
+
+<h4 class="addon-sdk-api-name" id="height"><code>height</code></h4>
+
+<p>The height of the panel in pixels.</p>
+
+<h4 class="addon-sdk-api-name" id="width"><code>width</code></h4>
+
+<p>The width of the panel in pixels.</p>
+
+<h4 class="addon-sdk-api-name" id="focus"><code>focus</code></h4>
+
+<p>Whether or not focus will be taken away when the panel is shown. This property is read-only.</p>
+
+<h4 class="addon-sdk-api-name" id="contentURL"><code>contentURL</code></h4>
+
+<p>The URL of content loaded into the panel. This can point to local content loaded from your add-on's "data" directory or remote content. Setting it updates the panel's content immediately.</p>
+
+<h4 class="addon-sdk-api-name" id="allow"><code>allow</code></h4>
+
+<p>An object describing permissions for the content. It contains a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content.</p>
+
+<h4 class="addon-sdk-api-name" id="contentScriptFile"><code>contentScriptFile</code></h4>
+
+<p>A local file URL or an array of local file URLs of content scripts to load. Content scripts specified by this property are loaded <em>before</em> those specified by the <code>contentScript</code> property.</p>
+
+<h4 class="addon-sdk-api-name" id="contentScript"><code>contentScript</code></h4>
+
+<p>A string or an array of strings containing the texts of content scripts to load. Content scripts specified by this property are loaded <em>after</em> those specified by the <code>contentScriptFile</code> property.</p>
+
+<h4 class="addon-sdk-api-name" id="contentScriptWhen"><code>contentScriptWhen</code></h4>
+
+<p>When to load the content scripts. This may have one of the following values:</p>
+
+<ul>
+ <li>"start": load content scripts immediately after the document element for the panel is inserted into the DOM, but before the DOM content itself has been loaded</li>
+ <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li>
+ <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the panel has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li>
+</ul>
+
+<h4 class="addon-sdk-api-name" id="contentScriptOptions"><code>contentScriptOptions</code></h4>
+
+<p>Read-only value exposed to content scripts under <code>addon.options</code> property.</p>
+
+<p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p>
+
+<h3 id="Events">Events</h3>
+
+<h4 class="addon-sdk-api-name" id="show"><code>show</code></h4>
+
+<p>This event is emitted when the panel is shown.</p>
+
+<h4 class="addon-sdk-api-name" id="hide"><code>hide</code></h4>
+
+<p>This event is emitted when the panel is hidden.</p>
+
+<h4 class="addon-sdk-api-name" id="message"><code>message</code></h4>
+
+<p>If you listen to this event you can receive message events from content scripts associated with this panel. When a content script posts a message using <code>self.postMessage()</code>, the message is delivered to the add-on code in the panel's <code>message</code> event.</p>
+
+<h5 id="Arguments">Arguments</h5>
+
+<p><strong>value</strong> : Listeners are passed a single argument which is the message posted from the content script. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p>
+
+<h4 class="addon-sdk-api-name" id="error"><code>error</code></h4>
+
+<p>This event is emitted when an uncaught runtime error occurs in one of the panel's content scripts.</p>
+
+<h5 id="Arguments_2">Arguments</h5>
+
+<p><strong>Error</strong> : Listeners are passed a single argument, the <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error">Error</a> object.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/tabs/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/tabs/index.html
new file mode 100644
index 0000000000..b85bb94ab3
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/tabs/index.html
@@ -0,0 +1,669 @@
+---
+title: tabs
+slug: Mozilla/Add-ons/SDK/High-Level_APIs/tabs
+translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/tabs
+---
+<p>{{AddonSidebar}}</p>
+
+<div class="note">
+<p>Stable</p>
+</div>
+
+<p><span class="seoSummary">打开、操作和访问标签页,以及接收标签页事件</span></p>
+
+<h2 id="用法">用法</h2>
+
+<h3 id="打开标签页">打开标签页</h3>
+
+<p>你可以注册事件监听器,以便在标签打开、关闭、完成DOM内容加载、被激活或被闲置时接收通知:</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+tabs.open("http://www.example.com");</pre>
+
+<h3 id="跟踪标签页">跟踪标签页</h3>
+
+<p>You can register event listeners to be notified when tabs open, close, finish loading DOM content, or are made active or inactive:</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+
+// Listen for tab openings.
+tabs.on('open', function onOpen(tab) {
+ myOpenTabs.push(tab);
+});
+
+// Listen for tab content loads.
+tabs.on('ready', function(tab) {
+ console.log('tab is loaded', tab.title, tab.url);
+});</pre>
+
+<h3 id="访问标签页">访问标签页</h3>
+
+<p>The module itself can be used as a list of all opened tabs across all windows. In particular, you can enumerate it:</p>
+
+<pre class="brush: js">var tabs = require('sdk/tabs');
+for (let tab of tabs)
+ console.log(tab.title);</pre>
+
+<p>You can also access individual tabs by index:</p>
+
+<pre class="brush: js">var tabs = require('sdk/tabs');
+
+tabs.on('ready', function () {
+ console.log('first: ' + tabs[0].title);
+ console.log('last: ' + tabs[tabs.length-1].title);
+});</pre>
+
+<p>You can access the currently active tab:</p>
+
+<pre class="brush: js">var tabs = require('sdk/tabs');
+
+tabs.on('activate', function () {
+ console.log('active: ' + tabs.activeTab.url);
+});</pre>
+
+<h3 id="跟踪单个标签页">跟踪单个标签页</h3>
+
+<p>Given a tab, you can register event listeners to be notified when the tab is closed, activated or deactivated, or when the page hosted by the tab is loaded or retrieved from the <a href="https://developer.mozilla.org/en-US/docs/Working_with_BFCache">"back-forward cache"</a>:</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+
+function onOpen(tab) {
+ console.log(tab.url + " is open");
+ tab.on("pageshow", logShow);
+ tab.on("activate", logActivate);
+ tab.on("deactivate", logDeactivate);
+ tab.on("close", logClose);
+}
+
+function logShow(tab) {
+ console.log(tab.url + " is loaded");
+}
+
+function logActivate(tab) {
+ console.log(tab.url + " is activated");
+}
+
+function logDeactivate(tab) {
+ console.log(tab.url + " is deactivated");
+}
+
+function logClose(tab) {
+ console.log(tab.url + " is closed");
+}
+
+tabs.on('open', onOpen);</pre>
+
+<h3 id="操作标签页">操作标签页</h3>
+
+<p>You can get and set various properties of tabs (but note that properties relating to the tab's content, such as the URL, will not contain valid values until after the tab's <code>ready</code> event fires). By setting the <code>url</code> property you can load a new page in the tab:</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+tabs.on('activate', function(tab) {
+ tab.url = "http://www.example.com";
+});</pre>
+
+<h3 id="在标签页中运行脚本">在标签页中运行脚本</h3>
+
+<p>You can attach a <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">content script</a> to the page hosted in a tab, and use that to access and manipulate the page's content (see the <a href="/en-US/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">Modifying the Page Hosted by a Tab</a> tutorial):</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+
+tabs.on('activate', function(tab) {
+ var worker = tab.attach({
+ contentScript: 'self.port.emit("html", document.body.innerHTML);'
+ });
+ worker.port.on("html", function(message) {
+ console.log(message)
+ })
+});</pre>
+
+<p>Note that <code>tab.attach</code> is tab-centric: if the user navigates to a new page in the same tab, then the worker and content scripts will be reattached to the new page.</p>
+
+<h3 id="附加样式表">附加样式表</h3>
+
+<div class="geckoVersionNote">
+<p>Firefox 34 新增。</p>
+</div>
+
+<p>You can't attach style sheets to a tab using <code>tab.attach()</code>, but from Firefox 34 onwards you can attach and detach them using the low-level <a href="/en-US/Add-ons/SDK/Low-Level_APIs/stylesheet_style">stylesheet/style</a> and <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_mod">content/mod</a> APIs. Here's an add-on that uses a toggle button to attach a stylesheet to the active tab, and detach it again. The stylesheet is called "style.css" and is located in the add-on's "data" directory:</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+var { attach, detach } = require('sdk/content/mod');
+var { Style } = require('sdk/stylesheet/style');
+var { ToggleButton } = require("sdk/ui/button/toggle");
+
+var style = Style({
+ uri: './style.css'
+});
+
+var button = ToggleButton({
+ id: "stylist",
+ label: "stylist",
+ icon: "./icon-16.png",
+ onChange: function(state) {
+ if (state.checked) {
+ attach(style, tabs.activeTab);
+ }
+ else {
+ detach(style, tabs.activeTab);
+ }
+ }
+});</pre>
+
+<h3 id="隐私窗口">隐私窗口</h3>
+
+<p>If your add-on has not opted into private browsing, then you won't see any tabs that are hosted by private browser windows.</p>
+
+<p>Tabs hosted by private browser windows won't be seen if you enumerate the <code>tabs</code> module itself, and you won't receive any events for them.</p>
+
+<p>To learn more about private windows, how to opt into private browsing, and how to support private browsing, refer to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing">documentation for the <code>private-browsing</code> module</a>.</p>
+
+<h3 id="转为XUL标签页">转为XUL标签页</h3>
+
+<p>To convert from the high-level <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#Tab"><code>Tab</code></a> objects used in this API to the low-level <a href="/en-US/docs/Mozilla/Tech/XUL/tab">XUL <code>tab</code></a> objects used in the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/tabs_utils"><code>tabs/utils</code></a> API and by traditional add-ons, use the <code>viewFor()</code> function exported by the <code>viewFor</code> module.</p>
+
+<p>To convert back the other way, from a XUL <code>tab</code> to a high-level <code>Tab</code> object, use the <code>modelFor()</code> function, exported by the <code>modelFor</code> module.</p>
+
+<p>Here's an example converting from a high-level <code>Tab</code> to a XUL <code>tab</code> and then back the other way:</p>
+
+<pre class="brush: js">var { modelFor } = require("sdk/model/core");
+var { viewFor } = require("sdk/view/core");
+
+var tabs = require("sdk/tabs");
+var tab_utils = require("sdk/tabs/utils");
+
+function mapHighLevelToLowLevel(tab) {
+  // get the XUL tab that corresponds to this high-level tab
+  var lowLevelTab = viewFor(tab);
+  // now we can, for example, access the tab's content directly
+  var browser = tab_utils.getBrowserForTab(lowLevelTab);
+  console.log(browser.contentDocument.body.innerHTML);
+  // get the high-level tab back from the XUL tab
+  var highLevelTab = modelFor(lowLevelTab);
+  console.log(highLevelTab.url);
+}
+
+tabs.on("ready", mapHighLevelToLowLevel);
+</pre>
+
+<p>Note that directly accessing XUL objects and web content like this means you're no longer protected by the compatibility guarantees made by the SDK's high-level APIs. In particular, your code might not work with <a href="http://billmccloskey.wordpress.com/2013/12/05/multiprocess-firefox/">multiprocess Firefox</a>.</p>
+
+<h2 id="全局变量">全局变量</h2>
+
+<h3 id="函数">函数</h3>
+
+<h4 class="addon-sdk-api-name" id="open(options)"><code>open(options)</code></h4>
+
+<p>Opens a new tab. The new tab will open in the active window or in a new window, depending on the <code>inNewWindow</code> option.</p>
+
+<p><strong>示例</strong></p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+
+// Open a new tab on active window and make tab active.
+tabs.open("http://www.mysite.com");
+
+// Open a new tab in a new window and make it active.
+tabs.open({
+ url: "http://www.mysite.com",
+ inNewWindow: true
+});
+
+// Open a new tab on active window in the background.
+tabs.open({
+ url: "http://www.mysite.com",
+ inBackground: true
+});
+
+// Open a new tab as an app tab and do something once it's open.
+tabs.open({
+ url: "http://www.mysite.com",
+ isPinned: true,
+ onOpen: function onOpen(tab) {
+ // do stuff like listen for content
+ // loading.
+ }
+});</pre>
+
+<h5 id="参数">参数</h5>
+
+<p><strong>options : object</strong><br>
+ 必选项:</p>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>url</td>
+ <td>string</td>
+ <td>
+ <p>String URL to be opened in the new tab. This is a required property.</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>可选项:</p>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>isPrivate</td>
+ <td>boolean</td>
+ <td>
+ <p>Boolean which will determine whether the new tab should be private or not. If your add-on does not support private browsing this will have no effect. See the <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing">private-browsing</a> documentation for more information. Defaults to <code>false</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>inNewWindow</td>
+ <td>boolean</td>
+ <td>
+ <p>If present and true, a new browser window will be opened and the URL will be opened in the first tab in that window. This is an optional property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>inBackground</td>
+ <td>boolean</td>
+ <td>
+ <p>If present and true, the new tab will be opened to the right of the active tab and will not be active. This is an optional property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>isPinned</td>
+ <td>boolean</td>
+ <td>
+ <p>If present and true, then the new tab will be pinned as an <a href="http://support.mozilla.com/en-US/kb/what-are-app-tabs">app tab</a>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onOpen</td>
+ <td>function</td>
+ <td>
+ <p>A callback function that will be registered for the 'open' event. This is an optional property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onClose</td>
+ <td>function</td>
+ <td>
+ <p>A callback function that will be registered for the 'close' event. This is an optional property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onReady</td>
+ <td>function</td>
+ <td>
+ <p>A callback function that will be registered for the 'ready' event. This is an optional property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onLoad</td>
+ <td>function</td>
+ <td>
+ <p>A callback function that will be registered for the 'load' event. This is an optional property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onPageShow</td>
+ <td>function</td>
+ <td>
+ <p>A callback function that will be registered for the 'pageshow' event. This is an optional property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onActivate</td>
+ <td>function</td>
+ <td>
+ <p>A callback function that will be registered for the 'activate' event. This is an optional property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onDeactivate</td>
+ <td>function</td>
+ <td>
+ <p>A callback function that will be registered for the 'deactivate' event. This is an optional property.</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="属性">属性</h3>
+
+<h4 class="addon-sdk-api-name" id="activeTab"><code>activeTab</code></h4>
+
+<p>The currently active tab in the active window. This property is read-only. To activate a <code>Tab</code> object, call its <code>activate</code> method.</p>
+
+<p><strong>示例</strong></p>
+
+<pre class="brush: js">// Get the active tab's title.
+var tabs = require("sdk/tabs");
+console.log("title of active tab is " + tabs.activeTab.title);</pre>
+
+<h4 class="addon-sdk-api-name" id="length"><code>length</code></h4>
+
+<p>The number of open tabs across all windows.</p>
+
+<h3 id="事件">事件</h3>
+
+<h4 class="addon-sdk-api-name" id="open"><code>open</code></h4>
+
+<p>This event is emitted when a new tab is opened. This does not mean that the content has loaded, only that the browser tab itself is fully visible to the user.</p>
+
+<p>Properties relating to the tab's content (for example: <code>title</code>, <code>favicon</code>, and <code>url</code>) will not be correct at this point. If you need to access these properties, listen for the <code>ready</code> event:</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+tabs.on('open', function(tab){
+ tab.on('ready', function(tab){
+ console.log(tab.url);
+ });
+});</pre>
+
+<h5 id="参数_2">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object that just opened.</p>
+
+<h4 class="addon-sdk-api-name" id="close"><code>close</code></h4>
+
+<p>This event is emitted when a tab is closed. When a window is closed this event will be emitted for each of the open tabs in that window.</p>
+
+<h5 id="参数_3">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object that has closed.</p>
+
+<h4 class="addon-sdk-api-name" id="ready"><code>ready</code></h4>
+
+<p>This event is emitted when the DOM for a tab's content is ready. It is equivalent to the <code>DOMContentLoaded</code> event for the given content page.</p>
+
+<p>A single tab will emit this event every time the DOM is loaded: so it will be emitted again if the tab's location changes or the content is reloaded.</p>
+
+<p>After this event has been emitted, all properties relating to the tab's content can be used.</p>
+
+<h5 id="参数_4">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object that has loaded.</p>
+
+<h4 class="addon-sdk-api-name" id="activate"><code>activate</code></h4>
+
+<p>This event is emitted when an inactive tab is made active.</p>
+
+<h5 id="参数_5">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object that has become active.</p>
+
+<h4 class="addon-sdk-api-name" id="deactivate"><code>deactivate</code></h4>
+
+<p>This event is emitted when the active tab is made inactive.</p>
+
+<h5 id="参数_6">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object that has become inactive.</p>
+
+<h2 id="Tab">Tab</h2>
+
+<p>A <code>Tab</code> instance represents a single open tab. It contains various tab properties, several methods for manipulation, as well as per-tab event registration.</p>
+
+<p>Tabs emit all the events described in the Events section. Listeners are passed the <code>Tab</code> object that triggered the event.</p>
+
+<h3 id="方法">方法</h3>
+
+<h4 class="addon-sdk-api-name" id="pin()"><code>pin()</code></h4>
+
+<p>Pins this tab as an <a href="http://support.mozilla.com/en-US/kb/what-are-app-tabs">app tab</a>.</p>
+
+<h4 class="addon-sdk-api-name" id="unpin()"><code>unpin()</code></h4>
+
+<p>Unpins this tab.</p>
+
+<h4 class="addon-sdk-api-name" id="close(callback)"><code>close(callback)</code></h4>
+
+<p>Closes this tab.</p>
+
+<h5 id="参数_7">参数</h5>
+
+<p><strong>callback : function</strong><br>
+ A function to be called when the tab finishes its closing process. This is an optional argument.</p>
+
+<h4 class="addon-sdk-api-name" id="reload()"><code>reload()</code></h4>
+
+<p>Reloads this tab.</p>
+
+<h4 class="addon-sdk-api-name" id="activate()"><code>activate()</code></h4>
+
+<p>Makes this tab active, which will bring this tab to the foreground.</p>
+
+<h4 class="addon-sdk-api-name" id="getThumbnail()"><code>getThumbnail()</code></h4>
+
+<p>Returns thumbnail data URI of the page currently loaded in this tab.</p>
+
+<h4 class="addon-sdk-api-name" id="attach(options)"><code>attach(options)</code></h4>
+
+<p>Attach one or more scripts to the document loaded in the tab. Note that by attaching inside <em>ready</em> event, this becomes tab-centric: if the user navigates to a new page in the same tab, then the content scripts will be reattached to the new page.</p>
+
+<p><strong>示例</strong></p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+
+tabs.on('ready', function(tab) {
+ var worker = tab.attach({
+ contentScript:
+ 'document.body.style.border = "5px solid red";'
+ });
+});</pre>
+
+<h5 id="参数_8">参数</h5>
+
+<p><strong>options : object</strong><br>
+ 可选项:</p>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>contentScriptFile</td>
+ <td>string,array</td>
+ <td>
+ <p>The local file URLs of content scripts to load. Content scripts specified by this option are loaded <em>before</em> those specified by the <code>contentScript</code> option. Optional.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>contentScript</td>
+ <td>string,array</td>
+ <td>
+ <p>A string or an array of strings of code to be evaluated in the context. Content scripts specified by this option are loaded <em>after</em> those specified by the <code>contentScriptFile</code> option. Optional.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>contentScriptOptions</td>
+ <td>object</td>
+ <td>
+ <p>You can use this option to define read-only values for your content scripts.</p>
+
+ <p>The option consists of an object literal listing <code>name:value</code> pairs for the values you want to provide to the content script. For example:</p>
+
+ <pre class="brush: js">
+// main.js
+
+const tabs = require("sdk/tabs");
+
+tabs.open({
+ url: "./page.html",
+ onReady: function(tab) {
+ tab.attach({
+ contentScriptFile: "./content-script.js",
+ contentScriptOptions: {
+ a: "blah"
+ }
+ });
+ }
+});</pre>
+
+ <p>The values are accessible to content scripts via the <code>self.options</code> property:</p>
+
+ <pre class="brush: js">
+// content-script.js
+
+alert(self.options.a);</pre>
+ </td>
+ </tr>
+ <tr>
+ <td>onMessage</td>
+ <td>function</td>
+ <td>
+ <p>A function called when the content worker receives a message from content scripts. Listeners are passed a single argument, the message posted from the content script. Optional.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onError</td>
+ <td>function</td>
+ <td>A function called when the content worker receives an error from content scripts. Listeners are passed a single argument, <code>error</code>, which is the error posted from the content script and an object of type <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error">Error</a>. Optional</td>
+ </tr>
+ </tbody>
+</table>
+
+<h5 id="返回">返回</h5>
+
+<p><strong>Worker</strong> : <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_worker">Worker</a> 对象能够用来和内容脚本通信。查看 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Content Scripts guide</a> 了解详细信息。</p>
+
+<h3 id="属性_2">属性</h3>
+
+<h4 class="addon-sdk-api-name" id="id"><code>id</code></h4>
+
+<p>The unique id for the tab. This property is read-only.</p>
+
+<h4 class="addon-sdk-api-name" id="title"><code>title</code></h4>
+
+<p>The title of the tab (usually the title of the page currently loaded in the tab) This property can be set to change the tab title.</p>
+
+<h4 class="addon-sdk-api-name" id="url"><code>url</code></h4>
+
+<p>The URL of the page currently loaded in the tab. This property can be set to load a different URL in the tab.</p>
+
+<h4 class="addon-sdk-api-name" id="favicon"><code>favicon</code></h4>
+
+<p>The URL of the favicon for the page currently loaded in the tab. This property is read-only.</p>
+
+<div class="warning">This property is deprecated. From version 1.15, use the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/places_favicon">favicon module's <code>getFavicon()</code></a> function instead.</div>
+
+<h4 class="addon-sdk-api-name" id="contentType"><code>contentType</code></h4>
+
+<div class="note">
+<p><strong>This is currently an experimental API, so we might change it in future releases.</strong></p>
+
+<p>Returns the MIME type that the document currently loaded in the tab is being rendered as. This may come from HTTP headers or other sources of MIME information, and might be affected by automatic type conversions performed by either the browser or extensions. This property is read-only.</p>
+</div>
+
+<h4 class="addon-sdk-api-name" id="index"><code>index</code></h4>
+
+<p>The index of the tab relative to other tabs in the application window. This property can be set to change its relative position.</p>
+
+<h4 class="addon-sdk-api-name" id="isPinned"><code>isPinned</code></h4>
+
+<p>Whether or not this tab is pinned as an <a href="http://support.mozilla.com/en-US/kb/what-are-app-tabs">app tab</a>. This property is read-only.</p>
+
+<h4 class="addon-sdk-api-name" id="window"><code>window</code></h4>
+
+<p><code>标签页的</code><a href="/en-US/Add-ons/SDK/High-Level_APIs/windows#BrowserWindow"><code>window</code></a>对象.</p>
+
+<h4 class="addon-sdk-api-name" id="readyState"><code>readyState</code></h4>
+
+<div class="geckoVersionNote">
+<p>Firefox 33 新增。</p>
+</div>
+
+<p>A string telling you the load state of the document hosted by this tab. This corresponds directly to <a href="/en-US/docs/Web/API/document.readyState"><code>Document.readyState</code></a>. It has one of four possible values:</p>
+
+<ul>
+ <li>"uninitialized": the tab's document is not yet loading</li>
+ <li>"loading": the tab's document is still in the process of loading</li>
+ <li>"interactive": the tab's document has loaded and is parsed, but resources such as images and stylesheets may still be loading</li>
+ <li>"complete": the tab's document and all resources are fully loaded</li>
+</ul>
+
+<p>Once a tab's <code>readyState</code> has entered "interactive", you can retrieve properties such as the document's URL.</p>
+
+<h3 id="事件_2">事件</h3>
+
+<h4 class="addon-sdk-api-name" id="close_2"><code>close</code></h4>
+
+<p>This event is emitted when the tab is closed. It's also emitted when the tab's window is closed.</p>
+
+<h5 id="参数_9">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object.</p>
+
+<h4 class="addon-sdk-api-name" id="ready_2"><code>ready</code></h4>
+
+<p>This event is emitted when the DOM for the tab's content is ready. It is equivalent to the <a href="https://developer.mozilla.org/en-US/docs/Web/Reference/Events/DOMContentLoaded"><code>DOMContentLoaded</code></a> event for the given content page. At this point the document itself is fully loaded and parsed, but resources such as stylesheets and images may still be loading.</p>
+
+<p>A single tab will emit this event every time the DOM is loaded: so it will be emitted again if the tab's location changes or the content is reloaded. After this event has been emitted, all properties relating to the tab's content can be used.</p>
+
+<h5 id="参数_10">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object.</p>
+
+<h4 class="addon-sdk-api-name" id="load"><code>load</code></h4>
+
+<p>This event is emitted when the page for the tab's content is loaded. It is equivalent to the <a href="https://developer.mozilla.org/en-US/docs/Web/Reference/Events/load"><code>load</code></a> event for the given content page. At this point the document and its resources, such as images and stylesheets, have finished loading.</p>
+
+<p>This event can be used for pages that do not have a <code>DOMContentLoaded</code> event, like images. For pages that have a <code>DOMContentLoaded</code> event, <code>load</code> is fired after <code>ready</code>.</p>
+
+<p>A single tab will emit this event every time the page is loaded: so it will be emitted again if the tab's location changes or the content is reloaded. After this event has been emitted, all properties relating to the tab's content can be used.</p>
+
+<h5 id="参数_11">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object.</p>
+
+<h4 class="addon-sdk-api-name" id="pageshow"><code>pageshow</code></h4>
+
+<p>The <code>pageshow</code> event is emitted when the page for a tab's content is loaded. It is equivalent to the <a href="https://developer.mozilla.org/en-US/docs/DOM/Mozilla_event_reference/pageshow"><code>pageshow</code></a> event for the given content page.</p>
+
+<p>This event is similar to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#load"><code>load</code></a> and <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#ready"><code>ready</code></a> events, except unlike <code>load</code> and <code>ready</code>, <code>pageshow</code> is triggered if the page was retrieved from the <a href="https://developer.mozilla.org/en-US/docs/Working_with_BFCache">bfcache</a>. This means that if the user loads a page, loads a new page, then moves back to the previous page using the "Back" button, the <code>pageshow</code> event is emitted when the user moves back to the previous page, while the <code>load</code> and <code>ready</code> events are not.</p>
+
+<p>This event is <em>not</em> emitted when the tab is made the active tab: to get notified about that, you need to listen to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#activate"><code>activate</code></a> event.</p>
+
+<p>After this event has been emitted, all properties relating to the tab's content can be used. It is emitted after <code>load</code> and <code>ready</code>.</p>
+
+<h5 id="参数_12">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object.</p>
+
+<p><strong>persisted</strong> : Listeners are passed a boolean value indicating whether or not the page was loaded from the <a href="https://developer.mozilla.org/en-US/docs/Working_with_BFCache">bfcache</a>.</p>
+
+<h4 class="addon-sdk-api-name" id="activate_2"><code>activate</code></h4>
+
+<p>This event is emitted when the tab is made active.</p>
+
+<p>Note that you cannot guarantee that a tab's content, or even its <code>url</code>, are initialized at the time <code>activate</code> is emitted. This is because when a new tab is opened, its <code>activate</code> event may be emitted before the content is loaded.</p>
+
+<p>You can use the tab's <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#readyState"><code>readyState</code></a> property to determine whether the tab's content and <code>url</code> will be available: if <code>readyState</code> is <code>uninitialized</code> or <code>loading</code>, then you can't access the tab's properties and must wait for the tab's <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#ready_2"><code>ready</code></a> event.</p>
+
+<h5 id="参数_13">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object.</p>
+
+<h4 class="addon-sdk-api-name" id="deactivate_2"><code>deactivate</code></h4>
+
+<p>This event is emitted when the tab is made inactive.</p>
+
+<h5 id="参数_14">参数</h5>
+
+<p><strong>Tab</strong> : Listeners are passed the tab object.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/url/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/url/index.html
new file mode 100644
index 0000000000..f98da9baf9
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/url/index.html
@@ -0,0 +1,191 @@
+---
+title: url
+slug: Mozilla/Add-ons/SDK/High-Level_APIs/url
+translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/url
+---
+<div class="note">
+<p>实验性的</p>
+</div>
+
+<p><span class="seoSummary">构建,验证,解析URL</span></p>
+
+<h2 id="Globals">Globals</h2>
+
+<h3 id="构造函数">构造函数</h3>
+
+<h4 class="addon-sdk-api-name" id="URL(source_base)"><code>URL(source, base)</code></h4>
+
+<p>URL构造函数可以创建一个URL对象,并验证提供的字符串是否是有效的URL。SDK中,任何接受URL参数的API,除非特殊说明,均接受的是此对象而不是字符串。</p>
+
+<h5 id="参数">参数</h5>
+
+<p><strong>source : string</strong><br>
+ 一个表示URL的字符串,如果接受的参数不是有效的URL字符串,此构造函数会抛出一个异常。</p>
+
+<p><strong>base : string</strong><br>
+ 一个设置的字符串,用来表示一个相对路径的源。</p>
+
+<h4 class="addon-sdk-api-name" id="DataURL(uri)"><code>DataURL(uri)</code></h4>
+
+<p>DataURL构造函数创建一个data: URL对象, 并验证提供的字符串是否是一个有效的data: URL。</p>
+
+<h5 id="参数_2">参数</h5>
+
+<p><strong>uri : string</strong><br>
+ 一个表示Data URL的字符串。如果它不是一个合法的URL字符串,此构造函数会抛出一个错误。</p>
+
+<h3 id="函数">函数</h3>
+
+<h4 class="addon-sdk-api-name" id="toFilename(url)"><code>toFilename(url)</code></h4>
+
+<p>尝试将给定的URL转换成本地文件路径。这个方法会自动尝试解决非文件协议, such as the <code>resource:</code> protocol, to their place on the file system. 除非URL无法转换,否则,本方法会将本地路径作为字符串返回。</p>
+
+<h5 id="参数_3">参数</h5>
+
+<p><strong>url : string</strong><br>
+ 字符串格式的URL。</p>
+
+<h5 id="返回">返回</h5>
+
+<p><strong>string</strong> : 转换后的本地路径字符串</p>
+
+<h4 class="addon-sdk-api-name" id="fromFilename(path)"><code>fromFilename(path)</code></h4>
+
+<p>讲一个给定的路径转换成 <code>file:</code> URL.</p>
+
+<h5 id="参数_4">参数</h5>
+
+<p><strong>path : string</strong><br>
+ 需要被转换的本地文件路径字符串。</p>
+
+<h5 id="Returns">Returns</h5>
+
+<p><strong>string</strong> : 转换后的字符串。</p>
+
+<h4 class="addon-sdk-api-name" id="isValidURI(uri)"><code>isValidURI(uri)</code></h4>
+
+<p>检查一个URL字符串是合法。 <code>isValidURI("http://mozilla.org")</code> 将返回 <code>true</code>, 而 <code>isValidURI("mozilla.org")</code> 将返回 <code>false</code>。</p>
+
+<h5 id="参数_5">参数</h5>
+
+<p><strong>uri : string</strong><br>
+ 需要被测试的URL。</p>
+
+<h5 id="Returns_2">Returns</h5>
+
+<p><strong>boolean</strong> : 代表字符串是否有效的布尔值。</p>
+
+<h4 class="addon-sdk-api-name" id="getTLD(url)"><code>getTLD(url)</code></h4>
+
+<p>返回给定域名的顶级域名: 内部使用的是 <a href="/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIEffectiveTLDService#getPublicSuffix()"><code>getPublicSuffix()</code></a> 。</p>
+
+<pre class="brush: js">var urls = require("sdk/url");
+console.log(urls.getTLD("http://www.bbc.co.uk/")); // "co.uk"
+console.log(urls.getTLD("https://developer.mozilla.org/")); // "org"</pre>
+
+<h5 id="参数_6">参数</h5>
+
+<p><strong>url : string</strong><br>
+ 给定的URL字符串</p>
+
+<h5 id="返回_2">返回</h5>
+
+<p><strong>string</strong> : 对应的顶级域名。</p>
+
+<h2 id="URL">URL</h2>
+
+<h3 id="方法">方法</h3>
+
+<h4 class="addon-sdk-api-name" id="toString()"><code>toString()</code></h4>
+
+<p>返回URL的字符表示形式。</p>
+
+<h5 id="返回_3">返回</h5>
+
+<p><strong>string</strong> : 字符串格式的URL。</p>
+
+<h3 id="属性">属性</h3>
+
+<h4 class="addon-sdk-api-name" id="scheme"><code>scheme</code></h4>
+
+<p>URL使用的协议</p>
+
+<h4 class="addon-sdk-api-name" id="userPass"><code>userPass</code></h4>
+
+<p>URL中的username:password 部分,<code>null</code> 表示不存在。</p>
+
+<h4 class="addon-sdk-api-name" id="host"><code>host</code></h4>
+
+<p>URL的主机部分。 <code>null</code> 表示无此部分。例子:</p>
+
+<pre class="brush: js">var url = require("sdk/url").URL("https://developer.mozilla.org/en-US/Add-ons");
+console.log(url.host); // developer.mozilla.org</pre>
+
+<h4 class="addon-sdk-api-name" id="port"><code>port</code></h4>
+
+<p>URL使用的端口。 <code>null</code> 表示不存在。</p>
+
+<h4 class="addon-sdk-api-name" id="path"><code>path</code></h4>
+
+<p>URL的路径部分,例子:</p>
+
+<pre class="brush: js">var url = require("sdk/url").URL("https://developer.mozilla.org/en-US/Add-ons");
+console.log(url.path); // /en-US/Add-ons</pre>
+
+<h4 class="addon-sdk-api-name" id="hostname"><code>hostname</code></h4>
+
+<p>表示URL的域的字符串。参见 <a href="/en-US/docs/Web/API/URLUtils.hostname"><code>window.location.hostname</code></a>。</p>
+
+<h4 class="addon-sdk-api-name" id="pathname"><code>pathname</code></h4>
+
+<p>从 <code>'/'</code>开始的路径字符串。参见 <a href="/en-US/docs/Web/API/URLUtils.pathname"><code>window.location.pathname</code></a>。</p>
+
+<h4 class="addon-sdk-api-name" id="hash"><code>hash</code></h4>
+
+<p>从 <code>'#'</code> 开始的hash字符串,参见 <a href="/en-US/docs/Web/API/URLUtils.hash"><code>window.location.hash</code></a>。</p>
+
+<h4 class="addon-sdk-api-name" id="href"><code>href</code></h4>
+
+<p>整个URL字符串,参见 <a href="/en-US/docs/Web/API/URLUtils.href"><code>window.location.href</code></a>。</p>
+
+<h4 class="addon-sdk-api-name" id="origin"><code>origin</code></h4>
+
+<p>该URL的源的字符串,参见 <a href="/en-US/docs/Web/API/URLUtils.origin"><code>window.location.origin</code></a>。</p>
+
+<h4 class="addon-sdk-api-name" id="protocol"><code>protocol</code></h4>
+
+<p>该URL使用的协议字符串,包括最后的<code>':',参见</code> <a href="/en-US/docs/Web/API/URLUtils.protocol"><code>window.location.protocol</code></a>。</p>
+
+<h4 class="addon-sdk-api-name" id="search"><code>search</code></h4>
+
+<p>以'?'开始的URL的参数段,包括最开始的<code>'?'</code>。 <code>参见</code><a href="/en-US/docs/Web/API/URLUtils.search"><code>window.location.search</code></a>.</p>
+
+<h2 id="DataURL">DataURL</h2>
+
+<h3 id="方法_2">方法</h3>
+
+<h4 class="addon-sdk-api-name" id="toString()_2"><code>toString()</code></h4>
+
+<p>返回数据的URL字符串形式。如果是 <code>base64</code> 的URL,数据会以base64编码方式编码。</p>
+
+<h5 id="返回_4">返回</h5>
+
+<p><strong>string</strong> : URL字符串</p>
+
+<h3 id="属性_2">属性</h3>
+
+<h4 class="addon-sdk-api-name" id="mimeType"><code>mimeType</code></h4>
+
+<p>数据的MIME类型,默认为空字符串。</p>
+
+<h4 class="addon-sdk-api-name" id="parameters"><code>parameters</code></h4>
+
+<p>一个HashMap的数据包含URL参数。默认情况下是一个空对象。</p>
+
+<h4 class="addon-sdk-api-name" id="base64"><code>base64</code></h4>
+
+<p><span>定义了</span><span>数据</span><span>属性</span><span>值</span><span>的编码。</span></p>
+
+<h4 class="addon-sdk-api-name" id="data"><code>data</code></h4>
+
+<p>包含数据的URL字符串。如果<code>URI</code>给构造函数包含<code>Base64</code>参数,这个字符串会被解码。</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/widget/index.html b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/widget/index.html
new file mode 100644
index 0000000000..3d374a0752
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/high-level_apis/widget/index.html
@@ -0,0 +1,839 @@
+---
+title: widget
+slug: Mozilla/Add-ons/SDK/High-Level_APIs/widget
+tags:
+ - ZH
+translation_of: Archive/Add-ons/Add-on_SDK/High-Level_APIs/widget
+---
+<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p>
+
+<div class="warning">
+<p>Deprecated in Firefox 29 and removed in Firefox 38.</p>
+
+<p>The widget API is deprecated from Firefox 29 onwards. Please see the <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui">ui module</a> for replacements. In particular, for a simple button, try the <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui#ActionButton">action button</a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui#ToggleButton">toggle button</a> APIs, and for a more complex widget try the <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui#Toolbar">toolbar</a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/ui#Sidebar">sidebar</a> APIs.</p>
+</div>
+
+<p><span class="seoSummary">Create a simple user interface for an add-on in Firefox's add-on bar.</span></p>
+
+<h2 id="Usage">Usage</h2>
+
+<p>"Widgets" are small pieces of content that live in the Firefox 4 <a href="https://developer.mozilla.org/en/The_add-on_bar">add-on bar</a>. They can be simple icons or complex web pages. You can attach <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panels</a> to them that open when they're clicked, or you can define a custom click handler to perform some other action, like opening a web page in a tab.</p>
+
+<p>There are a few advantages to using widgets over an ad hoc user interface. First, your users will be accustomed to interacting with add-ons via widgets and the add-on bar. Second, it allows Firefox to treat your interface as a first-class citizen. For example, in the future Firefox may allow the user to drag widgets from the add-on bar to other toolbars. By exposing your interface as a widget, your add-on would automatically inherit such functionality.</p>
+
+<h3 id="Creation_and_content">Creation and content</h3>
+
+<p>Widgets can contain images or arbitrary web content. You can include this content inline as a string by using the <code>content</code> property, or point to content using a URL with the <code>contentURL</code> property.</p>
+
+<p>Upon creation, the widget is automatically added to the add-on bar. You can set the width of a widget, but the height is fixed so as to fit in the add-on bar. If the content is an image, it is automatically scaled to be 16x16 pixels.</p>
+
+<p>For example, this widget contains an image, so it looks like a simple icon:</p>
+
+<pre class="brush: js">require("sdk/widget").Widget({
+ id: "mozilla-icon",
+ label: "My Mozilla Widget",
+ contentURL: "http://www.mozilla.org/favicon.ico"
+});</pre>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6695/widget-mozilla.png" style="display: block; height: 184px; margin-left: auto; margin-right: auto; width: 464px;">You can make <code>contentURL</code> point to an HTML or icon file which you have packaged inside your add-on. Just save the file in your add-on's <code>data</code> directory, and reference it using the <code>data.url()</code> method of the <a href="/en-US/Add-ons/SDK/High-Level_APIs/self"><code>self</code></a> module:</p>
+
+<pre class="brush: js">var data = require("sdk/self").data;
+
+require("sdk/widget").Widget({
+ id: "my-widget",
+ label: "My Widget",
+ contentURL: data.url("my-content.html")
+});</pre>
+
+<p>This widget contains an entire web page:</p>
+
+<pre class="brush: js">require("sdk/widget").Widget({
+ id: "hello-display",
+ label: "My Hello Widget",
+ content: "Hello!",
+ width: 50
+});</pre>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6605/widget-hello-text.png" style="display: block; height: 132px; margin-left: auto; margin-right: auto; width: 282px;">Widgets are quite small by default, so this example used the <code>width</code> property to grow it in order to show all the text.</p>
+
+<h3 id="Scripting_widget_content">Scripting widget content</h3>
+
+<p>To interact with the widget's content you need to load a separate script into the panel. In the SDK these scripts are called "content scripts" because they're explicitly used for interacting with web content.</p>
+
+<p>While content scripts can access the content they're attached to, they can't use the SDK's APIs. So implementing a complete solution usually means you have to send messages between the content script and the main add-on code.</p>
+
+<ul>
+ <li>
+ <p>You can specify one or more content scripts to load into the widget using the <code>contentScript</code> or <code>contentScriptFile</code> options to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/widget#Widget(options)"><code>Widget()</code> constructor</a>.</p>
+ </li>
+ <li>
+ <p>You can communicate with the script using either the <a href="/en-US/Add-ons/SDK/Guides/using_postMessage"><code>postMessage()</code></a> API or (preferably, usually) the <a href="/en-US/Add-ons/SDK/Guides/using_port"><code>port</code></a> API.</p>
+ </li>
+</ul>
+
+<div class="warning">
+<p>Unless your content script is extremely simple and consists only of a static string, don't use <code>contentScript</code>: if you do, you may have problems getting your add-on approved on AMO.</p>
+
+<p>Instead, keep the script in a separate file and load it using <code>contentScriptFile</code>. This makes your code easier to maintain, secure, debug and review.</p>
+</div>
+
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6607/widget-player-buttons.png" style="float: right; height: 132px; width: 282px;">For example, suppose we want to implement a media player as an add-on. We could implement the main user interface as a widget hosting an array of buttons to control play/pause/stop functions.</p>
+
+<p>We can then use a content script to listen for clicks on those buttons. But because content scripts can't use the SDK's APIs, we'll want the content script to send messages to the main add-on code, which can then implement the media player functions using the SDK.</p>
+
+<p>The widget's content is specified using HTML like this:</p>
+
+<pre class="brush: html"><code class="brush: js">&lt;html&gt;
+ &lt;body&gt;
+ &lt;img src="play.png" id="play-button"&gt;
+ &lt;img src="pause.png" id="pause-button"&gt;
+ &lt;img src="stop.png" id="stop-button"&gt;
+ &lt;/body&gt;
+&lt;/html&gt;</code></pre>
+
+<p>We just include three icons, and assign an ID to each one. This HTML file, and the icon files it references, are saved in the add-on's <code>data</code> directory.</p>
+
+<p>Next, we write a content script that listens for click events on each icon and sends the corresponding message to the main add-on code:</p>
+
+<pre class="brush: js">var play_button = document.getElementById("play-button");
+play_button.onclick = function() {
+ self.port.emit("play");
+}
+
+var pause_button = document.getElementById("pause-button");
+pause_button.onclick = function() {
+ self.port.emit("pause");
+}
+
+var stop_button = document.getElementById("stop-button");
+stop_button.onclick = function() {
+ self.port.emit("stop");
+}</pre>
+
+<p>We save this file in the add-on's <code>data</code> directory as "button-script.js". Finally. in the add-on's "main.js" file, we create the widget, assign it the HTML file and the content script, and listen for events from the content script:</p>
+
+<pre class="brush: js">const widgets = require("sdk/widget");
+const data = require("sdk/self").data;
+
+var player = widgets.Widget({
+ id: "player",
+ width: 72,
+ label: "Player",
+ contentURL: data.url("buttons.html"),
+ contentScriptFile: data.url("button-script.js")
+});
+
+player.port.on("play", function() {
+ console.log("playing");
+});
+
+player.port.on("pause", function() {
+ console.log("pausing");
+});
+
+player.port.on("stop", function() {
+ console.log("stopping");
+});</pre>
+
+<p>To learn much more about content scripts, see the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> guide.</p>
+
+<h3 id="Scripting_trusted_widget_content">Scripting trusted widget content</h3>
+
+<p>We've already seen that you can package HTML files in your add-on's <code>data</code> directory and use them to define the widget's content. We can call this "trusted" content, because unlike content loaded from a source outside the add-on, the add-on author knows exactly what it's doing. To interact with trusted content you don't need to use content scripts: you can just include a script from the HTML file in the normal way, using <code>script</code> tags.</p>
+
+<p>Like a content script, these scripts can communicate with the add-on code using the <a href="/en-US/Add-ons/SDK/Guides/using_postMessage"><code>postMessage()</code></a> API or the <a href="/en-US/Add-ons/SDK/Guides/using_port"><code>port</code></a> API. The crucial difference is that these scripts access the <code>postMessage</code> and <code>port</code> objects through the <code>addon</code> object, whereas content scripts access them through the <code>self</code> object.</p>
+
+<p>To show the difference, convert the <code>player</code> add-on above to use normal page scripts instead of content scripts.</p>
+
+<p>First, in the content script, change <code>self</code> to <code>addon</code>, and wrap it in a function:</p>
+
+<pre class="brush: js">function init() {
+ var play_button = document.getElementById("play-button");
+ play_button.onclick = function() {
+ addon.port.emit("play");
+ }
+
+ var pause_button = document.getElementById("pause-button");
+ pause_button.onclick = function() {
+ addon.port.emit("pause");
+ }
+
+ var stop_button = document.getElementById("stop-button");
+ stop_button.onclick = function() {
+ addon.port.emit("stop");
+ }
+}</pre>
+
+<p>Next, add a <code>script</code> tag to reference "button-script.js", and call its <code>init()</code> function on load:</p>
+
+<pre class="brush: html">&lt;html&gt;
+ &lt;head&gt;
+ &lt;script src="button-script.js"&gt;&lt;/script&gt;
+ &lt;/head&gt;
+ &lt;body onLoad="init()"&gt;
+ &lt;img src="play.png" id="play-button"&gt;
+ &lt;img src="pause.png" id="pause-button"&gt;
+ &lt;img src="stop.png" id="stop-button"&gt;
+ &lt;/body&gt;
+&lt;/html&gt;
+</pre>
+
+<p>Finally, remove the line attaching the content script from "main.js":</p>
+
+<pre class="brush: js">const widgets = require("sdk/widget");
+const data = require("sdk/self").data;
+
+var player = widgets.Widget({
+ id: "player",
+ width: 72,
+ label: "Player",
+ contentURL: data.url("buttons.html")
+});
+
+player.port.emit("init");
+
+player.port.on("play", function() {
+ console.log("playing");
+});
+
+player.port.on("pause", function() {
+ console.log("pausing");
+});
+
+player.port.on("stop", function() {
+ console.log("stopping");
+});</pre>
+
+<h3 id="Attaching_panels_to_widgets">Attaching panels to widgets</h3>
+
+<p>You can supply a <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a> to the widget's constructor: if you do this, the panel is automatically displayed when the user clicks the widget.</p>
+
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6609/widget-panel-clock.png" style="float: right; height: 222px; width: 214px;"></p>
+
+<pre class="brush: js">data = require("sdk/self").data
+
+var clockPanel = require("sdk/panel").Panel({
+ width:215,
+ height:160,
+ contentURL: data.url("clock.html")
+});
+
+require("sdk/widget").Widget({
+ id: "open-clock-btn",
+ label: "Clock",
+ contentURL: data.url("History.png"),
+ panel: clockPanel
+});</pre>
+
+<p>Note that this is, at the moment, the only way you can attach a panel to a widget.</p>
+
+<p>You must supply the panel in the widget's constructor for it to work. If you assign the panel to the widget after construction, the panel can still be shown but will not be anchored to the widget:</p>
+
+<pre class="brush: js">data = require("sdk/self").data
+
+var clockPanel = require("sdk/panel").Panel({
+ width:215,
+ height:160,
+ contentURL: data.url("clock.html")
+});
+
+widget = require("sdk/widget").Widget({
+ id: "open-clock-btn",
+ label: "Clock",
+ contentURL: data.url("History.png")
+});
+
+widget.panel = clockPanel;
+
+// Will not be anchored
+widget.panel.show();</pre>
+
+<p>Also, if you try to call <code>panel.show()</code> inside your widget's <code>click</code> event listener, the panel will not be anchored:</p>
+
+<pre class="brush: js">data = require("sdk/self").data
+
+var clockPanel = require("sdk/panel").Panel({
+ width:215,
+ height:160,
+ contentURL: data.url("clock.html")
+});
+
+require("sdk/widget").Widget({
+ id: "open-clock-btn",
+ label: "Clock",
+ contentURL: data.url("History.png"),
+ panel: clockPanel,
+ onClick: function() {
+ // Will not be anchored
+ this.panel.show();
+ }
+});</pre>
+
+<p>See <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=638142">bug 638142</a>.</p>
+
+<h3 id="Private_windows">Private windows</h3>
+
+<p>If your add-on has not opted into private browsing, then your widget will not appear in any private browser windows.</p>
+
+<p>To learn more about private windows, how to opt into private browsing, and how to support private browsing, refer to the <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing">documentation for the <code>private-browsing</code> module</a>.</p>
+
+<h3 id="Examples">Examples</h3>
+
+<p>For conciseness, these examples create their content scripts as strings and use the <code>contentScript</code> property. In your own add-ons, you will probably want to create your content scripts in separate files and pass their URLs using the <code>contentScriptFile</code> property. See <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">Working with Content Scripts</a> for more information.</p>
+
+<pre class="brush: js">var widgets = require("sdk/widget");
+
+// A basic click-able image widget.
+widgets.Widget({
+ id: "google-link",
+ label: "Widget with an image and a click handler",
+ contentURL: "http://www.google.com/favicon.ico",
+ onClick: function() {
+ require("sdk/tabs").activeTab.url = "http://www.google.com/";
+ }
+});</pre>
+
+<pre class="brush: js">// A widget that changes display on mouseover.
+widgets.Widget({
+ id: "mouseover-effect",
+ label: "Widget with changing image on mouseover",
+ contentURL: "http://www.yahoo.com/favicon.ico",
+ onMouseover: function() {
+ this.contentURL = "http://www.bing.com/favicon.ico";
+ },
+ onMouseout: function() {
+ this.contentURL = "http://www.yahoo.com/favicon.ico";
+ }
+});</pre>
+
+<pre class="brush: js">// A widget that updates content on a timer.
+widgets.Widget({
+ id: "auto-update-widget",
+ label: "Widget that updates content on a timer",
+ content: "0",
+ contentScript: 'setTimeout(function() {' +
+ ' document.body.innerHTML++;' +
+ '}, 2000)',
+ contentScriptWhen: "ready"
+});</pre>
+
+<pre class="brush: js">// A widget created with a specified width, that grows.
+var myWidget = widgets.Widget({
+ id: "widget-effect",
+ label: "Wide widget that grows wider on a timer",
+ content: "I'm getting longer.",
+ width: 50,
+});
+require("sdk/timers").setInterval(function() {
+ myWidget.width += 10;
+}, 1000);</pre>
+
+<pre class="brush: js">// A widget communicating bi-directionally with a content script.
+var widget = widgets.Widget({
+ id: "message-test",
+ label: "Bi-directional communication!",
+ content: "&lt;foo&gt;bar&lt;/foo&gt;",
+ contentScriptWhen: "ready",
+ contentScript: 'self.on("message", function(message) {' +
+ ' alert("Got message: " + message);' +
+ '});' +
+ 'self.postMessage("ready");',
+ onMessage: function(message) {
+ if (message == "ready")
+ widget.postMessage("me too");
+ }
+});</pre>
+
+<h2 id="Globals">Globals</h2>
+
+<h3 id="Constructors">Constructors</h3>
+
+<h4 class="addon-sdk-api-name" id="Widget(options)"><code>Widget(options)</code></h4>
+
+<p>Creates a new widget. The widget is immediately added to the add-on bar.</p>
+
+<h5 id="Parameters">Parameters</h5>
+
+<p><strong>options : object</strong><br>
+ Required options:</p>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>label</td>
+ <td>string</td>
+ <td>
+ <p>A string description of the widget used for accessibility, title bars, and error reporting.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>id</td>
+ <td>string</td>
+ <td>
+ <p>A string used to identify your widget in order to save its location when the user moves it in the browser. This string has to be unique and must not be changed over time.</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>Optional options:</p>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>content</td>
+ <td>string</td>
+ <td>
+ <p>An optional string value containing the displayed content of the widget. It may contain HTML. Widgets must have either the <code>content</code> property or the <code>contentURL</code> property set.</p>
+
+ <p>If the content is an image, it is automatically scaled to be 16x16 pixels.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>contentURL</td>
+ <td>string</td>
+ <td>
+ <p>An optional string URL to content to load into the widget. This can be local content or remote content, an image or web content. Widgets must have either the <code>content</code> property or the <code>contentURL</code> property set.</p>
+
+ <p>If the content is an image, it is automatically scaled to be 16x16 pixels.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>panel</td>
+ <td>Panel</td>
+ <td>
+ <p>An optional <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a> to open when the user clicks on the widget. Note: If you also register a "click" listener, it will be called instead of the panel being opened. However, you can show the panel from the listener by calling <code>this.panel.show()</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>width</td>
+ <td>integer</td>
+ <td>
+ <p>Optional width in pixels of the widget. If not given, a default width is used.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onClick</td>
+ <td>function</td>
+ <td>
+ <p>Include this to listen to the widget's <code>click</code> event.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onMessage</td>
+ <td>function</td>
+ <td>
+ <p>Include this to listen to the widget's <code>message</code> event.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onMouseover</td>
+ <td>function</td>
+ <td>
+ <p>Include this to listen to the widget's <code>mouseover</code> event.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onMouseout</td>
+ <td>function</td>
+ <td>
+ <p>Include this to listen to the widget's <code>mouseout</code> event.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onAttach</td>
+ <td>function</td>
+ <td>
+ <p>Include this to listen to the widget's <code>attach</code> event.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>tooltip</td>
+ <td>string</td>
+ <td>
+ <p>Optional text to show when the user's mouse hovers over the widget. If not given, the <code>label</code> is used.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>allow</td>
+ <td>object</td>
+ <td>
+ <p>An optional object describing permissions for the content. It should contain a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content. <code>script</code> defaults to true.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>contentScriptFile</td>
+ <td>string,array</td>
+ <td>
+ <p>A local file URL or an array of local file URLs of content scripts to load. Content scripts specified by this property are loaded <em>before</em> those specified by the <code>contentScript</code> property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>contentScript</td>
+ <td>string,array</td>
+ <td>
+ <p>A string or an array of strings containing the texts of content scripts to load. Content scripts specified by this property are loaded <em>after</em> those specified by the <code>contentScriptFile</code> property.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>contentScriptWhen</td>
+ <td>string</td>
+ <td>
+ <p>When to load the content scripts. This may take one of the following values:</p>
+
+ <ul>
+ <li>"start": load content scripts immediately after the document element for the widget is inserted into the DOM, but before the DOM content itself has been loaded</li>
+ <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li>
+ <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the widget has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li>
+ </ul>
+
+ <p>This property is optional and defaults to "end".</p>
+ </td>
+ </tr>
+ <tr>
+ <td>contentScriptOptions</td>
+ <td>object</td>
+ <td>
+ <p>Read-only value exposed to content scripts under <code>self.options</code> property.</p>
+
+ <p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="Widget">Widget</h2>
+
+<p>Represents a widget object.</p>
+
+<h3 id="Methods">Methods</h3>
+
+<h4 class="addon-sdk-api-name" id="destroy()"><code>destroy()</code></h4>
+
+<p>Removes the widget from the add-on bar.</p>
+
+<h4 class="addon-sdk-api-name" id="postMessage(data)"><code>postMessage(data)</code></h4>
+
+<p>Sends a message to the widget's content scripts.</p>
+
+<h5 id="Parameters_2">Parameters</h5>
+
+<p><strong>data : value</strong><br>
+ The message to send. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p>
+
+<h4 class="addon-sdk-api-name" id="on(type_listener)"><code>on(type, listener)</code></h4>
+
+<p>Registers an event listener with the widget.</p>
+
+<h5 id="Parameters_3">Parameters</h5>
+
+<p><strong>type : string</strong><br>
+ The type of event to listen for.</p>
+
+<p><strong>listener : function</strong><br>
+ The listener function that handles the event.</p>
+
+<h4 class="addon-sdk-api-name" id="removeListener(type_listener)"><code>removeListener(type, listener)</code></h4>
+
+<p>Unregisters an event listener from the widget.</p>
+
+<h5 id="Parameters_4">Parameters</h5>
+
+<p><strong>type : string</strong><br>
+ The type of event for which <code>listener</code> was registered.</p>
+
+<p><strong>listener : function</strong><br>
+ The listener function that was registered.</p>
+
+<h4 class="addon-sdk-api-name" id="getView(window)"><code>getView(window)</code></h4>
+
+<p>Retrieve a <code>WidgetView</code> instance of this widget relative to a browser window.</p>
+
+<h5 id="Parameters_5">Parameters</h5>
+
+<p><strong>window : BrowserWindow</strong><br>
+ The <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows#BrowserWindow">BrowserWindow</a> instance to match.</p>
+
+<h5 id="Returns">Returns</h5>
+
+<p><strong>WidgetView</strong> : A <code>WidgetView</code> instance associated with the browser window. Any changes subsequently applied to this object will only be applied to the widget attached to that window.</p>
+
+<h3 id="Properties">Properties</h3>
+
+<h4 class="addon-sdk-api-name" id="label"><code>label</code></h4>
+
+<p>The widget's label. Read-only.</p>
+
+<h4 class="addon-sdk-api-name" id="content"><code>content</code></h4>
+
+<p>A string containing the widget's content. It can contain HTML. Setting it updates the widget's appearance immediately. However, if the widget was created using <code>contentURL</code>, then this property is meaningless, and setting it has no effect.</p>
+
+<h4 class="addon-sdk-api-name" id="contentURL"><code>contentURL</code></h4>
+
+<p>The URL of content to load into the widget. This can point to local content loaded from your add-on's "data" directory or remote content, an image or web content. Setting it updates the widget's appearance immediately. However, if the widget was created using <code>content</code>, then this property is meaningless, and setting it has no effect.</p>
+
+<p>Setting the <code>contentURL</code> property will break the channel of communication between this widget and any content scripts it contains. Messages sent from the content script will no longer be received by the main add-on code, and vice versa. This issue is currently tracked as <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=825434">bug 825434</a>.</p>
+
+<h4 class="addon-sdk-api-name" id="panel"><code>panel</code></h4>
+
+<p>A <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a> to open when the user clicks on the widget.</p>
+
+<h4 class="addon-sdk-api-name" id="width"><code>width</code></h4>
+
+<p>The widget's width in pixels. Setting it updates the widget's appearance immediately.</p>
+
+<h4 class="addon-sdk-api-name" id="tooltip"><code>tooltip</code></h4>
+
+<p>The text of the tooltip that appears when the user hovers over the widget.</p>
+
+<h4 class="addon-sdk-api-name" id="allow"><code>allow</code></h4>
+
+<p>A object describing permissions for the content. It contains a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content.</p>
+
+<h4 class="addon-sdk-api-name" id="contentScriptFile"><code>contentScriptFile</code></h4>
+
+<p>A local file URL or an array of local file URLs of content scripts to load.</p>
+
+<h4 class="addon-sdk-api-name" id="contentScript"><code>contentScript</code></h4>
+
+<p>A string or an array of strings containing the texts of content scripts to load.</p>
+
+<h4 class="addon-sdk-api-name" id="contentScriptWhen"><code>contentScriptWhen</code></h4>
+
+<p>When to load the content scripts. This may have one of the following values:</p>
+
+<ul>
+ <li>"start": load content scripts immediately after the document element for the widget is inserted into the DOM, but before the DOM content itself has been loaded</li>
+ <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li>
+ <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the widget has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li>
+</ul>
+
+<h4 class="addon-sdk-api-name" id="contentScriptOptions"><code>contentScriptOptions</code></h4>
+
+<p>Read-only value exposed to content scripts under <code>self.options</code> property.</p>
+
+<p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p>
+
+<h4 class="addon-sdk-api-name" id="port"><code>port</code></h4>
+
+<p>Object that allows you to:</p>
+
+<ul>
+ <li>send events to the content script using the <code>port.emit</code> function</li>
+ <li>receive events from the content script using the <code>port.on</code> function</li>
+</ul>
+
+<p>See the guide to <a href="/en-US/Add-ons/SDK/Guides/using_port"> communicating using <code>port</code></a> for details.</p>
+
+<h3 id="Events">Events</h3>
+
+<h4 class="addon-sdk-api-name" id="attach"><code>attach</code></h4>
+
+<p>This event is emitted when a browser window is opened and a new <code>WidgetView</code> object is created. If the widget has a content script, this event is fired only when the content script is applied according to the <code>contentScriptWhen</code> attribute.</p>
+
+<h5 id="Arguments">Arguments</h5>
+
+<p><strong>WidgetView</strong> : The related <code>WidgetView</code> object.</p>
+
+<h4 class="addon-sdk-api-name" id="click"><code>click</code></h4>
+
+<p>This event is emitted when the widget is clicked.</p>
+
+<h5 id="Arguments_2">Arguments</h5>
+
+<p><strong>WidgetView</strong> : Listeners are passed a single argument which is the <code>WidgetView</code> that triggered the click event.</p>
+
+<h4 class="addon-sdk-api-name" id="message"><code>message</code></h4>
+
+<p>If you listen to this event you can receive message events from content scripts associated with this widget. When a content script posts a message using <code>self.postMessage()</code>, the message is delivered to the add-on code in the widget's <code>message</code> event.</p>
+
+<h5 id="Arguments_3">Arguments</h5>
+
+<p><strong>value</strong> : Listeners are passed a single argument which is the message posted from the content script. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p>
+
+<h4 class="addon-sdk-api-name" id="mouseover"><code>mouseover</code></h4>
+
+<p>This event is emitted when the user moves the mouse over the widget.</p>
+
+<h4 class="addon-sdk-api-name" id="mouseout"><code>mouseout</code></h4>
+
+<p>This event is emitted when the user moves the mouse away from the widget.</p>
+
+<h2 id="WidgetView">WidgetView</h2>
+
+<p>Represents a widget instance specific to one browser window.</p>
+
+<p>Anything you do to an instance of this object will only be applied to the instance attached to its browser window: widget instances attached to other browser windows will be unaffected.</p>
+
+<p>By contrast, any changes you make to an instance of the normal <code>Widget</code> class will be applied across all browser windows.</p>
+
+<p>This class has all the same methods, attributes and events as the <code>Widget</code> class except for the <code>getView</code> method and the <code>attach</code> event.</p>
+
+<p>In this example <code>WidgetView</code> is used to display different content for <code>http</code> and <code>https</code> schemes:</p>
+
+<pre class="brush: js">// A widget that update its content specifically to each window.
+var tabs = require("sdk/tabs");
+var windows = require("sdk/windows").browserWindows;
+var widget = require("sdk/widget").Widget({
+ id: "window-specific-test",
+ label: "Widget with content specific to each window",
+ content: " ",
+ width: 50
+});
+// Observe tab switch or document changes in each existing tab:
+function updateWidgetState(tab) {
+ var view = widget.getView(tab.window);
+ if (!view) return;
+ // Update widget displayed text:
+ view.content = tab.url.match(/^https/) ? "Secured" : "Unsafe";
+}
+tabs.on('ready', updateWidgetState);
+tabs.on('activate', updateWidgetState);</pre>
+
+<h3 id="Methods_2">Methods</h3>
+
+<h4 class="addon-sdk-api-name" id="destroy()_2"><code>destroy()</code></h4>
+
+<p>Removes the widget view from the add-on bar.</p>
+
+<h4 class="addon-sdk-api-name" id="postMessage(data)_2"><code>postMessage(data)</code></h4>
+
+<p>Sends a message to the widget view's content scripts.</p>
+
+<h5 id="Parameters_6">Parameters</h5>
+
+<p><strong>data : value</strong><br>
+ The message to send. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p>
+
+<h4 class="addon-sdk-api-name" id="on(type_listener)_2"><code>on(type, listener)</code></h4>
+
+<p>Registers an event listener with the widget view.</p>
+
+<h5 id="Parameters_7">Parameters</h5>
+
+<p><strong>type : string</strong><br>
+ The type of event to listen for.</p>
+
+<p><strong>listener : function</strong><br>
+ The listener function that handles the event.</p>
+
+<h4 class="addon-sdk-api-name" id="removeListener(type_listener)_2"><code>removeListener(type, listener)</code></h4>
+
+<p>Unregisters an event listener from the widget view.</p>
+
+<h5 id="Parameters_8">Parameters</h5>
+
+<p><strong>type : string</strong><br>
+ The type of event for which <code>listener</code> was registered.</p>
+
+<p><strong>listener : function</strong><br>
+ The listener function that was registered.</p>
+
+<h3 id="Properties_2">Properties</h3>
+
+<h4 class="addon-sdk-api-name" id="label_2"><code>label</code></h4>
+
+<p>The widget view's label. Read-only.</p>
+
+<h4 class="addon-sdk-api-name" id="content_2"><code>content</code></h4>
+
+<p>A string containing the widget view's content. It can contain HTML. Setting it updates the widget view's appearance immediately. However, if the widget view was created using <code>contentURL</code>, then this property is meaningless, and setting it has no effect.</p>
+
+<h4 class="addon-sdk-api-name" id="contentURL_2"><code>contentURL</code></h4>
+
+<p>The URL of content to load into the widget. This can point to local content loaded from your add-on's "data" directory or remote content, an image or web content. Setting it updates the widget's appearance immediately. However, if the widget was created using <code>content</code>, then this property is meaningless, and setting it has no effect.</p>
+
+<p>Setting the <code>contentURL</code> property will break the channel of communication between this widget and any content scripts it contains. Messages sent from the content script will no longer be received by the main add-on code, and vice versa. This issue is currently tracked as <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=825434">bug 825434</a>.</p>
+
+<h4 class="addon-sdk-api-name" id="panel_2"><code>panel</code></h4>
+
+<p>A <a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">panel</a> to open when the user clicks on the widget view.</p>
+
+<h4 class="addon-sdk-api-name" id="width_2"><code>width</code></h4>
+
+<p>The widget view's width in pixels. Setting it updates the widget view's appearance immediately.</p>
+
+<h4 class="addon-sdk-api-name" id="tooltip_2"><code>tooltip</code></h4>
+
+<p>The text of the tooltip that appears when the user hovers over the widget view.</p>
+
+<h4 class="addon-sdk-api-name" id="allow_2"><code>allow</code></h4>
+
+<p>A object describing permissions for the content. It contains a single key named <code>script</code> whose value is a boolean that indicates whether or not to execute script in the content.</p>
+
+<h4 class="addon-sdk-api-name" id="contentScriptFile_2"><code>contentScriptFile</code></h4>
+
+<p>A local file URL or an array of local file URLs of content scripts to load.</p>
+
+<h4 class="addon-sdk-api-name" id="contentScript_2"><code>contentScript</code></h4>
+
+<p>A string or an array of strings containing the texts of content scripts to load.</p>
+
+<h4 class="addon-sdk-api-name" id="contentScriptWhen_2"><code>contentScriptWhen</code></h4>
+
+<p>When to load the content scripts. This may have one of the following values:</p>
+
+<ul>
+ <li>"start": load content scripts immediately after the document element for the widget view is inserted into the DOM, but before the DOM content itself has been loaded</li>
+ <li>"ready": load content scripts once DOM content has been loaded, corresponding to the <a href="https://developer.mozilla.org/en/Gecko-Specific_DOM_Events">DOMContentLoaded</a> event</li>
+ <li>"end": load content scripts once all the content (DOM, JS, CSS, images) for the widget view has been loaded, at the time the <a href="https://developer.mozilla.org/en/DOM/window.onload">window.onload event</a> fires</li>
+</ul>
+
+<h4 class="addon-sdk-api-name" id="contentScriptOptions_2"><code>contentScriptOptions</code></h4>
+
+<p>Read-only value exposed to content scripts under <code>self.options</code> property.</p>
+
+<p>Any kind of jsonable value (object, array, string, etc.) can be used here. Optional.</p>
+
+<h4 class="addon-sdk-api-name" id="port_2"><code>port</code></h4>
+
+<p>Object that allows you to:</p>
+
+<ul>
+ <li>send events to the content script using the <code>port.emit</code> function</li>
+ <li>receive events from the content script using the <code>port.on</code></li>
+</ul>
+
+<p>See the guide to <a href="/en-US/Add-ons/SDK/Guides/using_port"> communicating using <code>port</code></a> for details.</p>
+
+<h3 id="Events_2">Events</h3>
+
+<h4 class="addon-sdk-api-name" id="detach"><code>detach</code></h4>
+
+<p>The <code>detach</code> event is fired when the widget view is removed from its related window. This can occur if the window is closed, Firefox exits, or the add-on is disabled.</p>
+
+<h4 class="addon-sdk-api-name" id="click_2"><code>click</code></h4>
+
+<p>This event is emitted when the widget view is clicked.</p>
+
+<h4 class="addon-sdk-api-name" id="message_2"><code>message</code></h4>
+
+<p>If you listen to this event you can receive message events from content scripts associated with this widget view. When a content script posts a message using <code>self.postMessage()</code>, the message is delivered to the add-on code in the widget view's <code>message</code> event.</p>
+
+<h5 id="Arguments_4">Arguments</h5>
+
+<p><strong>value</strong> : Listeners are passed a single argument which is the message posted from the content script. The message can be any <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/using_port#JSON-Serializable_Values">JSON-serializable value</a>.</p>
+
+<h4 class="addon-sdk-api-name" id="mouseover_2"><code>mouseover</code></h4>
+
+<p>This event is emitted when the user moves the mouse over the widget view.</p>
+
+<h4 class="addon-sdk-api-name" id="mouseout_2"><code>mouseout</code></h4>
+
+<p>This event is emitted when the user moves the mouse away from the widget view.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/index.html b/files/zh-cn/mozilla/add-ons/sdk/index.html
new file mode 100644
index 0000000000..3c6398ed48
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/index.html
@@ -0,0 +1,104 @@
+---
+title: 附加组件 SDK
+slug: Mozilla/Add-ons/SDK
+tags:
+ - More Example
+ - Need Tanslate
+ - TopicStub
+translation_of: Archive/Add-ons/Add-on_SDK
+---
+<div class="warning">
+<p>Support for extensions using XUL/XPCOM or the Add-on SDK was removed in Firefox 57, released November 2017. As there is no supported version of Firefox enabling these technologies, this page will be removed by December 2020.</p>
+
+<p>Add-ons using the techniques described in this document are considered a legacy technology in Firefox. Don't use these techniques to develop new add-ons. Use <a href="/en-US/Add-ons/WebExtensions">WebExtensions</a> instead. If you maintain an add-on which uses the techniques described here, consider migrating it to use WebExtensions.</p>
+
+<p><strong>Starting from <a href="https://wiki.mozilla.org/RapidRelease/Calendar">Firefox 53</a>, no new legacy add-ons will be accepted on addons.mozilla.org (AMO) for desktop Firefox and Firefox for Android.</strong></p>
+
+<p><strong>Starting from <a href="https://wiki.mozilla.org/RapidRelease/Calendar">Firefox 57</a>, only extensions developed using WebExtensions APIs will be supported on Desktop Firefox and Firefox for Android. </strong></p>
+
+<p>Even before Firefox 57, changes coming up in the Firefox platform will break many legacy extensions. These changes include multiprocess Firefox (e10s), sandboxing, and multiple content processes. Legacy extensions that are affected by these changes should migrate to use WebExtensions APIs if they can. See the <a href="https://blog.mozilla.org/addons/2017/02/16/the-road-to-firefox-57-compatibility-milestones/">"Compatibility Milestones" document</a> for more information.</p>
+
+<p>A wiki page containing <a href="https://wiki.mozilla.org/Add-ons/developer/communication">resources, migration paths, office hours, and more</a>, is available to help developers transition to the new technologies.</p>
+</div>
+
+<p>你可以使用Add-on SDK来开发Firefox的附加组件。你可以使用各种各样的标准Web技术:JavaScript, HTML和CSS。该SDK不仅包括一些用来创建附加组件的 JavaScript API,还提供了开发、运行、测试、打包附加组件的一些工具。</p>
+
+<hr>
+<h3 id="教程">教程</h3>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><code><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials#getting-started">快速入门</a></code></dt>
+ <dd>如何<a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/SDK/Tools/jpm">安装SDK</a>并<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_started">使用jpm工具</a>开发、测试、打包附加组件</dd>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials#interact-with-the-browser">与浏览器交互</a></dt>
+ <dd><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Open_a_Web_Page">打开网页</a>,<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Listen_for_Page_Load">监听页面加载</a>,<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/List_Open_Tabs">列出打开的标签页</a>。</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials#development-techniques">开发技术</a></dt>
+ <dd>学习常用开发技术,如<a href="/zh-CN/Add-ons/SDK/Tutorials/Unit_testing">单元测试</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Logging">日志</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Creating_Reusable_Modules">创建可复用模块</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/l10n">本地化</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Mobile_development">移动开发</a></dd>
+</dl>
+</div>
+
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials#create-user-interfaces">创建用户界面组件</a></dt>
+ <dd>创建用户界面组件如<a href="/zh-CN/Add-ons/SDK/Tutorials/Adding_a_Button_to_the_Toolbar">工具条按钮</a>, <a href="/zh-CN/Add-ons/SDK/Tutorials/Add_a_Context_Menu_Item">上下文菜单</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Add_a_Menu_Item_to_Firefox">菜单项</a>,<a href="/zh-CN/Add-ons/SDK/Tutorials/Display_a_Popup">对话框</a>。</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials#modify-web-pages">修改网页</a></dt>
+ <dd>
+ <p>通过<a href="/zh-CN/docs//zh-CN/Add-ons/SDK/Tutorials/Modifying_Web_Pages_Based_on_URL">URL匹配</a>修改页面或者动态<a href="/zh-CN/docs//zh-CN/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">修改某个tab选项卡</a>。</p>
+ </dd>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator">将其组合在一起</a></dt>
+ <dd>关于注释器的附加组件的例子演示.</dd>
+</dl>
+</div>
+</div>
+
+<hr>
+<h3 id="指南">指南</h3>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/Add-ons/SDK/Guides#contributors-guide"><span class="short_text" id="result_box" lang="zh-CN"><span class="op_dict_text2">贡献者</span><span>指南</span></span></a></dt>
+ <dd>学习<a href="/zh-CN/Add-ons/SDK/Guides/Getting_Started">如何开始构建</a> SDK和关于SDK最重要的术语, 如 <a href="/zh-CN/Add-ons/SDK/Guides/Modules">模块</a>, <a href="/zh-CN/Add-ons/SDK/Guides/Classes_and_Inheritance"> 类和继承</a>, <a href="/zh-CN/Add-ons/SDK/Guides/Private_Properties">私有属性</a>, <a href="/zh-CN/Add-ons/SDK/Guides/Content_Processes">内容处理</a>.</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Guides#sdk-infrastructure">SDK的基础构建</a></dt>
+ <dd>SDK的底层技术方面: <a href="/zh-CN/Add-ons/SDK/Guides/Module_structure_of_the_SDK">模块</a>,<a href="/zh-CN/Add-ons/SDK/Guides/Program_ID">程序ID</a>, <a href="/zh-CN/Add-ons/SDK/Guides/Firefox_Compatibility">Firefox 兼容</a>的规则定义.</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Guides/Content_Scripts"><span class="short_text" id="result_box" lang="zh-CN"><span>内容</span><span>脚本</span></span></a></dt>
+ <dd>
+ <div class="output-bd" dir="ltr">
+ <p class="ordinary-output target-output"><span>一个详细的</span><span>指南</span><span>内容脚本</span></p>
+ </div>
+ </dd>
+</dl>
+</div>
+
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/Add-ons/SDK/Guides#sdk-idioms">SDK语法</a></dt>
+ <dd>SDK的事件框架和插件的脚本和内容脚本之间的区别。</dd>
+ <dd>SDK的 <a href="/zh-CN/Add-ons/SDK/Guides/Working_with_Events">事件框架</a> 和 <a href="/zh-CN/Add-ons/SDK/Guides/Two_Types_of_Scripts">add-on scripts 和 content scripts 的</a>区别.</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Guides/XUL_Migration_Guide">XUL 迁移</a></dt>
+ <dd>指导  <a href="/zh-CN/Add-ons/SDK/Guides/XUL_Migration_Guide">移植 XUL add-ons 到 SDK</a>. 本指南包括 <a href="/zh-CN/Add-ons/SDK/Guides/XUL_vs_SDK">两工具</a> 和 一个 <a href="/zh-CN/Add-ons/SDK/Guides/Porting_the_Library_Detector">工作实例</a> 比较 XUL 和 add-on.</dd>
+</dl>
+</div>
+</div>
+
+<hr>
+<h3 id="参考"><span class="short_text" id="result_box" lang="zh-CN"><span>参考</span></span></h3>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/Add-ons/SDK/High-Level_APIs">高级API</a></dt>
+ <dd>高级SDK API的参考文档.</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tools">工具参考</a></dt>
+ <dd>用于 <a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tools/jpm">jpm工具</a> 开发的参考文档, 测试, 打包add-ons, 全局 <a href="/zh-CN/Add-ons/SDK/Tools/console">控制台</a>记录, 和<a href="/zh-CN/Add-ons/SDK/Tools/package_json">package.json</a> 文件.</dd>
+</dl>
+</div>
+
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/Add-ons/SDK/Low-Level_APIs">低级API</a></dt>
+ <dd>低级SDK API的参考文档.</dd>
+</dl>
+</div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/index.html b/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/index.html
new file mode 100644
index 0000000000..673c369430
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/index.html
@@ -0,0 +1,26 @@
+---
+title: 低层 API
+slug: Mozilla/Add-ons/SDK/Low-Level_APIs
+translation_of: Archive/Add-ons/Add-on_SDK/Low-Level_APIs
+---
+<p>{{AddonSidebar}}</p>
+
+<p>本节的模块实现了低层的 API,这些模块大至分为三类:</p>
+
+<ul>
+ <li>
+ <p>基础工具,比如 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/util_collection">collection</a>。很多 add-ons 都有可能使用这个类别的模块。</p>
+ </li>
+ <li>
+ <p>为高层模块构建分块,比如 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/event_core">events</a> 和 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_worker">worker</a>。你更有可能使用它们构建你自己德尔模块,来扩展 SDK 本身。</p>
+ </li>
+ <li>
+ <p>权限模块,露出强大的低层功能,比如<a href="/en-US/Add-ons/SDK/Low-Level_APIs/window_utils">window/utils</a> 和 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/net_xhr">net/xhr</a>。你可以使用这些模块,但是应该意识到获取访问权限的代价是必须采取更加详尽的预防措施。大部分情况下这些模块在"高层API中"有着简单的更加严格的同类模块。(例如,<a href="/en-US/Add-ons/SDK/High-Level_APIs/windows">windows</a> 或 <a href="/en-US/Add-ons/SDK/High-Level_APIs/request">request</a>)。</p>
+ </li>
+</ul>
+
+<p>这些模块仍在开发中,我们预期在将来发布的版本中会做出不兼容的变更。</p>
+
+<p>{{ LandingPageListSubpages ("/zh-CN/Add-ons/SDK/Low-Level_APIs", 5) }}</p>
+
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/test_assert/index.html b/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/test_assert/index.html
new file mode 100644
index 0000000000..5f7537ec42
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/test_assert/index.html
@@ -0,0 +1,283 @@
+---
+title: test/assert
+slug: Mozilla/Add-ons/SDK/Low-Level_APIs/test_assert
+translation_of: Archive/Add-ons/Add-on_SDK/Low-Level_APIs/test_assert
+---
+<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p>
+
+<div class="note">
+<p>Unstable</p>
+</div>
+
+<p>实现在 <a href="http://wiki.commonjs.org/wiki/Unit_Testing/1.1">CommonJS Unit Testing specification version 1.1</a> 其中定义的断言接口。</p>
+
+<h2 id="Usage">Usage</h2>
+
+<p>To use the <code>assert</code> module, write a set of unit tests following the instructions in the <a href="/en-US/Add-ons/SDK/Tutorials/Unit_testing">unit testing tutorial</a>. Each test will be passed an <code>Assert</code> object when you run the tests using <a href="/en-US/Add-ons/SDK/Tools/jpm"><code>jpm test</code></a>. You can use this object to make assertions about your program's state.</p>
+
+<p>For example:</p>
+
+<pre class="brush: js">var a = 1;
+
+exports["test value of a"] = function(assert) {
+ assert.ok(a == 1, "test that a is 1");
+}
+
+require("sdk/test").run(exports);</pre>
+
+<h2 id="Globals">Globals</h2>
+
+<h3 id="Constructors">Constructors</h3>
+
+<h4 class="addon-sdk-api-name" id="Assert(logger)"><code>Assert(logger)</code></h4>
+
+<p>Create a new Assert object. This function is only called by the unit test framework, and not by unit tests themselves.</p>
+
+<h5 id="Parameters">Parameters</h5>
+
+<p><strong>logger : object</strong><br>
+ Object used to log the results of assertions.</p>
+
+<h2 id="Assert">Assert</h2>
+
+<p>An object used to make assertions about a program's state in order to implement unit tests.</p>
+
+<p>The <code>Assert</code> object's interface is defined by the <a href="http://wiki.commonjs.org/wiki/Unit_Testing/1.1">CommonJS Unit Testing specification, version 1.1</a>.</p>
+
+<h3 id="Methods">Methods</h3>
+
+<h4 class="addon-sdk-api-name" id="ok(guard_message)"><code>ok(guard, message)</code></h4>
+
+<p>Tests whether an expression evaluates to true.</p>
+
+<pre class="brush: js">assert.ok(a == 1, "test that a is equal to one");</pre>
+
+<p>This is equivalent to:</p>
+
+<pre class="brush: js">assert.equal(a == 1, true, "test that a is equal to one");</pre>
+
+<h5 id="Parameters_2">Parameters</h5>
+
+<p><strong>guard : expression</strong><br>
+ The expression to evaluate.</p>
+
+<p><strong>message : string</strong><br>
+ Optional message to log, providing extra information about the test.</p>
+
+<h4 class="addon-sdk-api-name" id="equal(actual_expected_message)"><code>equal(actual, expected, message)</code></h4>
+
+<p>Tests shallow, coercive equality with <code>==</code>:</p>
+
+<pre class="brush: js">assert.equal(1, 1, "test that one is one");</pre>
+
+<h5 id="Parameters_3">Parameters</h5>
+
+<p><strong>actual : object</strong><br>
+ The actual result.</p>
+
+<p><strong>expected : object</strong><br>
+ The expected result.</p>
+
+<p><strong>message : string</strong><br>
+ Optional message to log, providing extra information about the test.</p>
+
+<h4 class="addon-sdk-api-name" id="notEqual(actual_expected_message)"><code>notEqual(actual, expected, message)</code></h4>
+
+<p>Tests that two objects are not equal, using <code>!=</code>:</p>
+
+<pre class="brush: js">assert.notEqual(1, 2, "test that one is not two");</pre>
+
+<h5 id="Parameters_4">Parameters</h5>
+
+<p><strong>actual : object</strong><br>
+ The actual result.</p>
+
+<p><strong>expected : object</strong><br>
+ The expected result.</p>
+
+<p><strong>message : string</strong><br>
+ Optional message to log, providing extra information about the test.</p>
+
+<h4 class="addon-sdk-api-name" id="deepEqual(actual_expected_message)"><code>deepEqual(actual, expected, message)</code></h4>
+
+<p>Tests that two objects have a deep equality relation. Deep equality is defined in the <a href="http://wiki.commonjs.org/wiki/Unit_Testing/1.0#Assert">CommonJS specification for Assert</a>, item 7, which is quoted here:</p>
+
+<div class="quote">
+<ol>
+ <li>All identical values are equivalent, as determined by ===.</li>
+ <li>If the expected value is a Date object, the actual value is equivalent if it is also a Date object that refers to the same time.</li>
+ <li>Other pairs that do not both pass typeof value == "object", equivalence is determined by ==.</li>
+ <li>For all other Object pairs, including Array objects, equivalence is determined by having the same number of owned properties (as verified with Object.prototype.hasOwnProperty.call), the same set of keys (although not necessarily the same order), equivalent values for every corresponding key, and an identical "prototype" property. Note: this accounts for both named and indexed properties on Arrays.</li>
+</ol>
+</div>
+
+<pre class="brush: js">assert.deepEqual({ a: "foo" }, { a: "foo" }, "equivalent objects");</pre>
+
+<h5 id="Parameters_5">Parameters</h5>
+
+<p><strong>actual : object</strong><br>
+ The actual result.</p>
+
+<p><strong>expected : object</strong><br>
+ The expected result.</p>
+
+<p><strong>message : string</strong><br>
+ Optional message to log, providing extra information about the test.</p>
+
+<h4 class="addon-sdk-api-name" id="notDeepEqual(actual_expected_message)"><code>notDeepEqual(actual, expected, message)</code></h4>
+
+<p>Tests that two objects do not have a deep equality relation, using the negation of the test for deep equality:</p>
+
+<pre class="brush: js">assert.notDeepEqual({ a: "foo" }, Object.create({ a: "foo" }),
+ "object's inherit from different prototypes");</pre>
+
+<h5 id="Parameters_6">Parameters</h5>
+
+<p><strong>actual : object</strong><br>
+ The actual result.</p>
+
+<p><strong>expected : object</strong><br>
+ The expected result.</p>
+
+<p><strong>message : string</strong><br>
+ Optional message to log, providing extra information about the test.</p>
+
+<h4 class="addon-sdk-api-name" id="strictEqual(actual_expected_message)"><code>strictEqual(actual, expected, message)</code></h4>
+
+<p>Tests that two objects are equal, using the strict equality operator <code>===</code>:</p>
+
+<pre class="brush: js">// This test will pass, because "==" will perform type conversion
+exports["test coercive equality"] = function(assert) {
+ assert.equal(1, "1", "test coercive equality between 1 and '1'");
+}
+
+// This test will fail, because the types are different
+exports["test strict equality"] = function(assert) {
+ assert.strictEqual(1, "1", "test strict equality between 1 and '1'");
+}</pre>
+
+<h5 id="Parameters_7">Parameters</h5>
+
+<p><strong>actual : object</strong><br>
+ The actual result.</p>
+
+<p><strong>expected : object</strong><br>
+ The expected result.</p>
+
+<p><strong>message : string</strong><br>
+ Optional message to log, providing extra information about the test.</p>
+
+<h4 class="addon-sdk-api-name" id="notStrictEqual(actual_expected_message)"><code>notStrictEqual(actual, expected, message)</code></h4>
+
+<p>Tests that two objects are not equal, using the negation of the strict equality operator <code>===</code>:</p>
+
+<pre class="brush: js">// This test will fail, because "==" will perform type conversion
+exports["test coercive equality"] = function(assert) {
+ assert.notEqual(1, "1", "test coercive equality between 1 and '1'");
+}
+
+// This test will pass, because the types are different
+exports["test strict equality"] = function(assert) {
+ assert.notStrictEqual(1, "1", "test strict equality between 1 and '1'");
+}</pre>
+
+<h5 id="Parameters_8">Parameters</h5>
+
+<p><strong>actual : object</strong><br>
+ The actual result.</p>
+
+<p><strong>expected : object</strong><br>
+ The expected result.</p>
+
+<p><strong>message : string</strong><br>
+ Optional message to log, providing extra information about the test.</p>
+
+<h4 class="addon-sdk-api-name" id="throws(block_error_message)"><code>throws(block, error, message)</code></h4>
+
+<p>Assert that a block of code throws the expected exception.</p>
+
+<p>This method takes an optional <code>Error</code> argument:</p>
+
+<ul>
+ <li>
+ <p>to check that the exception thrown is of the expected type, pass a constructor function: the exception thrown must be an instance of the object returned by that function.</p>
+ </li>
+ <li>
+ <p>to check that the exception thrown contains a specific message, pass a regular expression here: the <code>message</code> property of the exception thrown must match the regular expression</p>
+ </li>
+</ul>
+
+
+<p>For example, suppose we define two different custom exceptions:</p>
+
+<pre class="brush: js">function MyError(message) {
+ this.name = "MyError";
+ this.message = message || "Default Message";
+}
+
+MyError.prototype = new Error();
+MyError.prototype.constructor = MyError;
+
+function AnotherError(message) {
+ this.name = "AnotherError";
+ this.message = message || "Default Message";
+ console.log(this.message);
+}
+
+AnotherError.prototype = new Error();
+AnotherError.prototype.constructor = AnotherError;</pre>
+
+<p>We can check the type of exception by passing a function as the <code>Error</code> argument:</p>
+
+<pre class="brush: js">exports["test exception type 1 expected to pass"] = function(assert) {
+ assert.throws(function() {
+ throw new MyError("custom message");
+ },
+ MyError,
+ "test throwing a specific exception");
+}
+
+exports["test exception type 2 expected to fail"] = function(assert) {
+ assert.throws(function() {
+ throw new MyError("custom message");
+ },
+ AnotherError,
+ "test throwing a specific exception");
+}</pre>
+
+<p>We can check the message by passing a regular expression:</p>
+
+<pre class="brush: js">exports["test exception message 1 expected to pass"] = function(assert) {
+ assert.throws(function() {
+ throw new MyError("custom message");
+ },
+ /custom message/,
+ "test throwing a specific message");
+}
+
+exports["test exception message 2 expected to pass"] = function(assert) {
+ assert.throws(function() {
+ throw new AnotherError("custom message");
+ },
+ /custom message/,
+ "test throwing a specific exception");
+}
+
+exports["test exception message 3 expected to fail"] = function(assert) {
+ assert.throws(function() {
+ throw new MyError("another message");
+ },
+ /custom message/,
+ "test throwing a specific message");
+}</pre>
+
+<h5 id="Parameters_9">Parameters</h5>
+
+<p><strong>block : block</strong><br>
+ The block of code to test.</p>
+
+<p><strong>error : function|RegExp</strong><br>
+ Either a constructor function returning the type of exception expected, or a regular expression expected to match the exception's <code>message</code> property.</p>
+
+<p><strong>message : string</strong><br>
+ Optional message to log, providing extra information about the test.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/ui_button_action/index.html b/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/ui_button_action/index.html
new file mode 100644
index 0000000000..d826b15d7f
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/low-level_apis/ui_button_action/index.html
@@ -0,0 +1,526 @@
+---
+title: ui/button/action
+slug: Mozilla/Add-ons/SDK/Low-Level_APIs/ui_button_action
+translation_of: Archive/Add-ons/Add-on_SDK/Low-Level_APIs/ui_button_action
+---
+<div class="note">
+ <p>实验性的(译者备注:暂不翻译,可能会废弃)</p>
+</div>
+<p><span class="seoSummary">Add a button to the Firefox user interface.</span> With this module you can create buttons that display icons and can respond to click events.</p>
+<h2 id="Usage">Usage</h2>
+<h3 id="Creating_buttons"><br>
+ Creating buttons</h3>
+<p>To create a button you must give it an ID, an icon, and a label:</p>
+<pre class="brush: js">var { ActionButton } = require("sdk/ui/button/action");
+
+var button = ActionButton({
+    id: "my-button",
+    label: "my button",
+    icon: {
+      "16": "./firefox-16.png",
+      "32": "./firefox-32.png"
+    },
+    onClick: function(state) {
+        console.log("button '" + state.label + "' was clicked");
+    }
+  });</pre>
+<p>By default, the button appears in the Firefox toolbar:</p>
+<p><img alt="" src="https://mdn.mozillademos.org/files/6803/action-button-toolbar.png" style="width: 381px; height: 201px; display: block; margin-left: auto; margin-right: auto;">However, users can move it to the Firefox menu panel using the <a href="https://support.mozilla.org/en-US/kb/customize-firefox-controls-buttons-and-toolbars">toolbar customization feature</a>:</p>
+<p><img alt="" src="https://mdn.mozillademos.org/files/6809/action-button-menu.png" style="width: 381px; height: 573px; display: block; margin-left: auto; margin-right: auto;"></p>
+<h3 id="Badged_buttons">Badged buttons</h3>
+<div class="geckoVersionNote">
+ <p>New in Firefox 36.</p>
+</div>
+<p>You can add a "badge" to a button using its <code>badge</code> property. This can be a number or a string, and you can update it at any time. By default the badge's color is red, but you can set your own color using the <code>badgeColor</code> property, specified as a CSS <a href="/en-US/docs/Web/CSS/color_value"><code>&lt;color&gt;</code></a> value:</p>
+<pre class="brush: js">var { ToggleButton } = require("sdk/ui/button/toggle");
+
+var button = ToggleButton({
+    id: "my-button1",
+    label: "my button1",
+    icon: "./icon-16.png",
+    onChange: changed,
+    badge: 0,
+    badgeColor: "#00AAAA"
+  });
+
+function changed(state) {
+  button.badge = state.badge + 1;
+  if (state.checked) {
+    button.badgeColor = "#AA00AA";
+  }
+  else {
+    button.badgeColor = "#00AAAA";
+  }
+}</pre>
+<p><img alt="" src="https://mdn.mozillademos.org/files/9067/badge.png" style="width: 383px; height: 202px; display: block; margin-left: auto; margin-right: auto;"></p>
+<h3 id="Specifying_multiple_icons">Specifying multiple icons</h3>
+<p>You can specify just one icon, or multiple icons in different sizes.</p>
+<p>If you specify multiple icons, Firefox will select the best-fitting icon based on the device screen resolution and the place the icon appears. For example, in the screenshots above, Firefox uses the small icon when the button is in the toolbar and the large icon when the button is in the menu panel. Read more about specifying icons in the reference documentation for the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#ActionButton(options)"><code>ActionButton</code> constructor</a>.</p>
+<h3 id="Responding_to_click_events">Responding to click events</h3>
+<p>You can respond to click events by assigning a listener to the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click"><code>click</code></a> event. You can do this in the button's constructor, by assigning the listener to the <code>onClick</code> option. You can also add, or change, the listener afterwards:</p>
+<pre class="brush: js">var { ActionButton } = require("sdk/ui/button/action");
+
+var button = ActionButton({
+ id: "my-button",
+ label: "my button",
+ icon: {
+ "16": "./firefox-16.png",
+ "32": "./firefox-32.png"
+ },
+ onClick: firstClick
+ });
+
+function firstClick(state) {
+ console.log("You clicked '" + state.label + "'");
+ button.removeListener("click", firstClick);
+ button.on("click", subsequentClicks);
+}
+
+function subsequentClicks(state) {
+ console.log("You clicked '" + state.label + "' again");
+}</pre>
+<p>The listener is passed a <code>state</code> object that contains all the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Properties">properties</a>.</p>
+<p>You can generate click events programmatically with the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click()"><code>click()</code></a> method.</p>
+<h3 id="Disabling_buttons">Disabling buttons</h3>
+<p>You can disable a button by setting its <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#disabled"><code>disabled</code></a> property to <code>true</code>. A disabled button will not generate click events and its icon will appear disabled:</p>
+<p><img alt="" src="https://mdn.mozillademos.org/files/6805/action-button-toolbar-disabled.png" style="width: 381px; height: 201px; display: block; margin-left: auto; margin-right: auto;"></p>
+<h3 id="Updating_state">Updating state</h3>
+<p>You can update all the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Properties">properties</a> except for its <code>id</code>.</p>
+<p>By default, the button has global state: that is, its properties are the same across all open windows and tabs, and updating them updates the button's state across all open windows and tabs.</p>
+<p>You can set state to be specific to a window or tab using the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#state()"><code>state()</code></a> method. To set state like this, call <code>state()</code> with 2 parameters:</p>
+<ul>
+ <li>the first parameter is a <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows"><code>window</code></a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs#Tab"><code>tab</code></a> object or as a shorthand, the string "window" for the currently active window, or the string "tab" for the currently active tab</li>
+ <li>the second parameter is an object containing the state properties you wish to update.</li>
+</ul>
+<p>Here's an add-on with a button that disables itself when you click it, but only for the currently active window:</p>
+<pre class="brush: js">var { ActionButton } = require("sdk/ui/button/action");
+
+var button = ActionButton({
+ id: "my-button",
+ label: "my button",
+ icon: {
+ "16": "./firefox-16.png",
+ "32": "./firefox-32.png"
+ },
+ onClick: disableForThisWindow
+ });
+
+function disableForThisWindow(state) {
+ button.state("window", {
+ disabled: true
+ });
+}</pre>
+<p>To fetch the state for a specific window or tab, call <code>state()</code>, passing in the window or tab you are interested in, and it will return the state:</p>
+<pre class="brush: js">var labelForActiveTab = button.state("tab").label;</pre>
+<p>To learn more about this, see the API documentation for <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#state()"><code>state()</code></a>.</p>
+<h3 id="Destroying_buttons">Destroying buttons</h3>
+<p>When you've finished with a button, destroy it by calling its <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#destroy()"><code>destroy()</code></a> method. After that, any attempts to access any of its properties or to call any of its methods will throw exceptions.</p>
+<h2 id="Globals">Globals</h2>
+<h3 id="Constructors">Constructors</h3>
+<h4 class="addon-sdk-api-name" id="ActionButton(options)"><code>ActionButton(options)</code></h4>
+<p>Creates an action button.</p>
+<h5 id="Parameters">Parameters</h5>
+<p><strong>options : object</strong><br>
+ Required options:</p>
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>id</td>
+ <td>string</td>
+ <td>
+ <p>The button's ID. This is used internally to keep track of this button. The ID must be unique within your add-on.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>label</td>
+ <td>string</td>
+ <td>
+ <p>The button's human-readable label. When the button is in the toolbar, this appears in a tooltip, and when the button is in the menu, it appears underneath the button as a legend.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>icon</td>
+ <td>url, string, object</td>
+ <td>
+ <p>One or more icons for the button. You can specify this in one of three ways: </p>
+ <ul>
+ <li><strong>as a resource:// URL</strong> pointing at an icon file in your add-on's "data" directory, typically constructed using <em><code>self.data.url(iconfile)</code></em></li>
+ <li><strong>as a relative path</strong>: a string in the form "./iconfile", where "iconfile" is a relative path to the icon file beginning in your add-on's "data" directory</li>
+ <li><strong>as an object, or dictionary of key-value pairs</strong>. Here you can specify a range of sizes for your button's icon. Each key-value pair specifies an icon:
+ <ul>
+ <li>each value specifies an image file as a resource:// URL or relative path.</li>
+ <li>each key must be a numeric string such as "16", or "32", which represents the size in pixels of the corresponding image.</li>
+ </ul>
+ </li>
+ </ul>
+ <pre class="brush: js">
+var { ActionButton } = require('sdk/ui/button/action');
+var self = require("sdk/self");
+
+var button1 = ActionButton({
+    id: "my-button1",
+    label: "my button1",
+    icon: self.data.url("firefox-16.png")
+  });
+
+var button2 = ActionButton({
+    id: "my-button2",
+    label: "my button2",
+    icon: "./firefox-16.png"
+  });
+
+var button3 = ActionButton({
+    id: "my-button3",
+    label: "my button3",
+    icon: {
+      "16" : "./firefox-16.png",
+      "32" : "./firefox-32.png",
+      "64" : "./firefox-64.png"
+    }
+  });</pre>
+ <p>If you use the final form, Firefox will automatically choose the best-fit icon for your button, depending on the device screen resolution and where the button is in the UI. On a device with a "normal" screen resolution, the toolbar has space for 18 x 18 pixels and the menu panel has space for 32 x 32 pixels. On a high resolution screen (such as a <a href="https://en.wikipedia.org/wiki/Retina_Display">HiDPI</a> display), these are doubled to 36 x 36 and 64 x 64 pixels, respectively. So you can supply three icon files:</p>
+ <pre class="brush: js">
+icon: {
+ "16": "./addon16.png",
+ "32": "./addon32.png",
+ "64": "./addon64.png"
+}</pre>
+ <p>This will look fine in both toolbar and menu panel, and for both screen resolutions. However, the icons in the toolbar will not quite fill the space available, so you can instead supply four icons:</p>
+ <pre class="brush: js">
+icon: {
+ "18": "./addon18.png", // toolbar icon non HiDPI
+ "32": "./addon32.png", // menu panel icon non HiDPI
+ "36": "./addon36.png", // toolbar icon HiDPI
+ "64": "./addon64.png" // menu panel icon HiDPI
+}
+</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+<p>Optional options:</p>
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col"> </th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>disabled</td>
+ <td>boolean</td>
+ <td>
+ <p>Determines whether the button is disabled. Disabled buttons appear disabled in the UI, and do not respond to clicks. Defaults to false.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>onClick</td>
+ <td>function</td>
+ <td>
+ <p>Click handler for the button.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>badge</td>
+ <td>Number or String</td>
+ <td>
+ <div class="geckoVersionNote">
+ <p>New in Firefox 36.</p>
+ </div>
+ <p><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Badged_buttons">Badge</a> to attach to the button.</p>
+ </td>
+ </tr>
+ <tr>
+ <td>badgeColor</td>
+ <td>CSS <a href="/en-US/docs/Web/CSS/color_value">&lt;color&gt;</a> value</td>
+ <td>
+ <div class="geckoVersionNote">
+ <p>New in Firefox 36.</p>
+ </div>
+ <p>Color for the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Badged_buttons">badge</a>. If <code>badgeColor</code> is omitted and <code>badge</code> is specified, then the badge is red.</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+<h2 id="ActionButton">ActionButton</h2>
+<h3 id="Methods">Methods</h3>
+<h4 class="addon-sdk-api-name" id="click()"><code>click()</code></h4>
+<p>Click the button. This will cause the button to generate the <code>click</code> event:</p>
+<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action');
+
+var button = ActionButton({
+ id: "my-button",
+ label: "my button",
+ icon: {
+ "16": "./firefox-16.png",
+ "32": "./firefox-32.png"
+ },
+ onClick: function(state) {
+ console.log("You clicked '" + state.label + "'");
+ }
+});
+
+button.click();
+</pre>
+<h4 class="addon-sdk-api-name" id="state()"><code>state()</code></h4>
+<p>Get or set the button's state for a specific window or tab.</p>
+<p>By default, a button's properties are global, meaning that they are the same across all open windows and tabs, and that if you update these properties, then they are updated across all windows and tabs. But sometimes you want a button attached to one window (or tab) to have a different state to a button attached to a different window (or tab). That's what <code>state()</code> is for.</p>
+<p>To set a button's properties for a specific window or tab, call <code>state()</code>, passing it the <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows"><code>window</code></a> or <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tab</code></a> you want the property to apply to, and the property value to set. A special shortcut allows you to pass the string "window" or "tab" to select the currently active window or tab.</p>
+<p>For example, if you have a button like this:</p>
+<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action');
+
+var button = ActionButton({
+ id: "my-button",
+ label: "default",
+ icon: "./firefox-16.png"
+});</pre>
+<p>You can change its label for only the currently active window like this:</p>
+<pre class="brush: js">button.state("window", {
+ "label" : "window-specific label"
+});</pre>
+<p>You can change its label for only the currently active tab like this:</p>
+<pre class="brush: js">button.state("tab", {
+ "label" : "tab-specific label"
+});
+</pre>
+<p>To fetch the button state for a specific window or tab, call <code>state()</code>, passing it the window or tab you're interested in, and it will return a state object containing all the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Properties">properties</a> for the button associated with that window or tab. Again. you can use the strings "window" or "tab" as shortcuts. For example, this add-on:</p>
+<ul>
+ <li>creates a button with a default label</li>
+ <li>opens a new tab</li>
+ <li>sets a new label only for the new tab</li>
+ <li>logs the result of accessing the global label, the window-specific label, and each of the 2 tab-specific labels</li>
+</ul>
+<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action');
+var tabs = require("sdk/tabs");
+
+var button = ActionButton({
+  id: "my-button",
+  label: "default label",
+  icon: "./firefox-16.png"
+});
+
+tabs.open({
+  url: "https://mozilla.org/",
+  onOpen: onNewTab
+});
+
+function onNewTab(tab) {
+  // Modify the label only for the new tab
+  button.state(tab, {
+    "label" : "tab-specific label"
+  });
+
+  // access the global label -&gt; "default label"
+  console.log(button.label);
+
+  // access the window's label -&gt; "default label"
+  console.log(button.state("window").label);
+
+  // access the first tab's label -&gt; "default label"
+  console.log(button.state(tabs[0]).label);
+
+  // access the second tab's label -&gt; "tab-specific label"
+  console.log(button.state(tabs[1]).label);
+}</pre>
+<p>Setting a property won't affect a more-specific property setting. For example, if you have a window with two tabs, and you set a tab-specific label, then set the window-specific label, this will not overwrite the tab-specific label:</p>
+<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action');
+var tabs = require("sdk/tabs");
+
+var button = ActionButton({
+  id: "my-button",
+  label: "default label",
+  icon: "./firefox-16.png"
+});
+
+tabs.open({
+  url: "https://mozilla.org/",
+  onOpen: onNewTab
+});
+
+function onNewTab(tab) {
+  // Modify the label only for the new tab
+  button.state(tab, {
+    "label" : "tab-specific label"
+  });
+
+  // Modify the label for the window
+  button.state("window", {
+    "label" : "window-specific label"
+  });
+
+  // access the global label -&gt; "default label"
+  console.log(button.label);
+
+  // access the window's label -&gt; "window-specific label"
+  console.log(button.state("window").label);
+
+  // access the first tab's label -&gt; "window-specific label"
+  console.log(button.state(tabs[0]).label);
+
+  // access the second tab's label -&gt; "tab-specific label"
+  console.log(button.state(tabs[1]).label);
+}</pre>
+<p>The best way to think of this is as a tree: the global state is the root, followed by the state for each window, followed by the state for each tab in a window. If a property value for a node in the tree has not been set explicitly using <code>state()</code>, then it inherits its value from the next level up. So if you have one window containing two tabs, and have set the button's <code>label</code> only for tab A, then tab B will inherit <code>label</code>'s value from the window, and changing the value for the window will implicitly change the value for tab B.</p>
+<p>To delete a tab- or window-specific state, assign <code>null</code> to the property. After that, the property will inherit its value from the less-specific state as before:</p>
+<pre class="brush: js">var { ActionButton } = require('sdk/ui/button/action');
+var tabs = require("sdk/tabs");
+
+var button = ActionButton({
+ id: "my-button",
+ label: "default label",
+ icon: "./firefox-16.png"
+});
+
+tabs.open({
+ url: "https://mozilla.org/",
+ onOpen: onNewTab
+});
+
+function onNewTab(tab) {
+ // Modify the label only for the new tab
+ button.state(tab, {
+ "label" : "tab-specific label"
+ });
+
+ // Modify the label for the window
+ button.state("window", {
+ "label" : "window-specific label"
+ });
+
+ // access the global label -&gt; "default label"
+ console.log(button.label);
+
+ // access the window's label -&gt; "window-specific label"
+ console.log(button.state("window").label);
+
+ // access the first tab's label -&gt; "window-specific label"
+ console.log(button.state(tabs[0]).label);
+
+ // access the second tab's label -&gt; "tab-specific label"
+ console.log(button.state(tabs[1]).label);
+
+ // Reset the tab-specific state
+ button.state(tab, null);
+
+ // access the second tab's label -&gt; "window-specific label"
+ console.log(button.state(tabs[1]).label);
+}</pre>
+<p>Finally, you can pass the button itself into <code>state()</code>. This is an alternative way to set or get the global state. The reason for using this, rather than setting properties individually, is that you can define an object with the properties to set in one place, then apply it to the global state with a single line:</p>
+<pre class="brush: js">const defaultState = {
+  "label": "default label",
+  "icon": "./default.png",
+}
+
+const differentState = {
+  "label": "different label",
+  "icon": "./different.png",
+}
+
+var { ActionButton } = require("sdk/ui/button/action");
+
+var button = ActionButton({
+    id: "default-label",
+    label: "default label",
+    icon: "./default.png",
+    onClick: function(state) {
+      if (button.label == "default label") {
+        button.state(button, differentState);
+      }
+      else {
+        button.state(button, defaultState);
+      }
+      console.log(button.state(button).label);
+      console.log(button.state(button).icon);
+    }
+  });
+</pre>
+<h5 id="Parameters_2">Parameters</h5>
+<p><strong>target : button, tab, window, string</strong></p>
+<ul>
+ <li>To set or get the global state, this needs to be the <code>button</code> instance.</li>
+ <li>To get or set window-specific state, this needs to be the <a href="/en-US/Add-ons/SDK/High-Level_APIs/windows"><code>window</code></a> object for which you wish to set a specific state, or the string "window" to select the currently active window.</li>
+ <li>To get or set tab-specific state this needs to be the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tab</code></a> object for which you wish to set a specific state, or the string "tab" to select the currently active tab.</li>
+</ul>
+<p><strong>state : object, null</strong><br>
+ Include this parameter only if you are setting state. It is an object containing all the properties you wish to set. For example:</p>
+<pre class="brush: js">button.state("tab", {
+ "label" : "tab-specific label",
+ "icon": "./tab-specific-icon.ico"
+});</pre>
+<p>To reset state, pass null:</p>
+<pre class="brush: js">button.state("tab", null);</pre>
+<h5 id="Returns">Returns</h5>
+<p><strong>state</strong> : if you have passed the second <code>state</code> argument to make this function a setter, it returns <code>undefined</code>. Otherwise, it functions as a getter and returns the button's state for the specified object. This logs the state for the button associated with the currently active tab:</p>
+<pre class="brush: js">console.log(button.state("tab"));</pre>
+<p>This object represents a snapshot of the state at the time <code>state()</code> is called. It is not kept up to date with changes made to the button:</p>
+<pre class="brush: js">button.label = "foo";
+var state = button.state(button);
+button.label = "bar";
+console.log(state.label) // foo</pre>
+<h4 class="addon-sdk-api-name" id="on()"><code>on()</code></h4>
+<p>Add a listener to an event emitted by the button. The button only emits one type of event, <code><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click">click</a></code>:</p>
+<pre class="brush: js">button.on("click", handleClick)
+
+function handleClick(state) {
+ console.log("button '" + state.label + "' was clicked");
+}</pre>
+<h5 id="Parameters_3">Parameters</h5>
+<p><strong>event : string</strong><br>
+ The event to listen for. Action buttons only emit one type of event, "<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click"><code>click</code></a>".</p>
+<p><strong>listener : function</strong><br>
+ Function that will be called on click.</p>
+<h4 class="addon-sdk-api-name" id="once()"><code>once()</code></h4>
+<p>Assign a listener to the first occurrence only of an event emitted by the button. The button only emits one type of event, <code><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click">click</a></code>. The listener is automatically removed after the first time the event is emitted.</p>
+<h5 id="Parameters_4">Parameters</h5>
+<p><strong>event : string</strong><br>
+ The event to listen for. Action buttons only emit one type of event, "<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click"><code>click</code></a>".</p>
+<p><strong>listener : function</strong><br>
+ Function that will be called on click.</p>
+<h4 class="addon-sdk-api-name" id="removeListener()"><code>removeListener()</code></h4>
+<p>Removes an event listener. For example, this code is equivalent to <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#once()"><code>once()</code></a>:</p>
+<pre class="brush: js">button.on("click", handleClick)
+
+function handleClick(state) {
+ console.log("button '" + state.label + "' was clicked");
+ button.removeListener("click", handleClick);
+} </pre>
+<h5 id="Parameters_5">Parameters</h5>
+<p><strong>event : string</strong><br>
+ The event to listener is listening for. Action buttons only emit one type of event, "<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#click"><code>click</code></a>".</p>
+<p><strong>listener : function</strong><br>
+ The listener to remove.</p>
+<h4 class="addon-sdk-api-name" id="destroy()"><code>destroy()</code></h4>
+<p>Destroy the button. After calling this function, the button will no longer appear in the UI, and accessing any of its properties or methods will throw an error.</p>
+<h3 id="Properties">Properties</h3>
+<h4 class="addon-sdk-api-name" id="id"><code>id</code></h4>
+<p>The button's unique ID. This is read-only.</p>
+<h4 class="addon-sdk-api-name" id="label"><code>label</code></h4>
+<p>The button's label.</p>
+<h4 class="addon-sdk-api-name" id="icon"><code>icon</code></h4>
+<p>The button's icon or icons, as a URL, relative path, or object containing a set of key-value pairs.</p>
+<h4 class="addon-sdk-api-name" id="disabled"><code>disabled</code></h4>
+<p>Boolean property indicating whether or not the button is disabled.</p>
+<h4 class="addon-sdk-api-name" id="badge"><code>badge</code></h4>
+<div class="geckoVersionNote">
+ <p>New in Firefox 36.</p>
+</div>
+<p>Value to attach to the button as a <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Badged_buttons">badge</a>. May be a number or a string.</p>
+<h4 class="addon-sdk-api-name" id="badgeColor"><code>badgeColor</code></h4>
+<div class="geckoVersionNote">
+ <p>New in Firefox 36.</p>
+</div>
+<p>Color for the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Badged_buttons">badge</a>, specified as a CSS <a href="/en-US/docs/Web/CSS/color_value">&lt;color&gt;</a> value.</p>
+<h3 id="Events">Events</h3>
+<h4 class="addon-sdk-api-name" id="click"><code>click</code></h4>
+<p>This event is emitted when a user clicks the button or your add-on calls the button's <code>click()</code> method.</p>
+<h5 id="Arguments">Arguments</h5>
+<p><strong>state</strong> : The button's state. This contains all the button's <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Properties">properties</a>.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tools/index.html b/files/zh-cn/mozilla/add-ons/sdk/tools/index.html
new file mode 100644
index 0000000000..8c67b4644e
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tools/index.html
@@ -0,0 +1,14 @@
+---
+title: Tools
+slug: Mozilla/Add-ons/SDK/Tools
+tags:
+ - Add-on SDK
+ - CFX
+ - JPM
+ - NeedsTranslation
+ - TopicStub
+translation_of: Archive/Add-ons/Add-on_SDK/Tools
+---
+<p>Articles listed here provide a reference for the SDK's tools:</p>
+
+<p>{{ LandingPageListSubpages ("/en-US/Add-ons/SDK/Tools", 7) }}</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tools/jpm/index.html b/files/zh-cn/mozilla/add-ons/sdk/tools/jpm/index.html
new file mode 100644
index 0000000000..db429ef078
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tools/jpm/index.html
@@ -0,0 +1,652 @@
+---
+title: jpm
+slug: Mozilla/Add-ons/SDK/Tools/jpm
+tags:
+ - Add-on SDK
+ - JPM
+translation_of: Archive/Add-ons/Add-on_SDK/Tools/jpm
+---
+<p>{{AddonSidebar}}</p>
+
+<div class="note">
+<p>你能在Firefox 38或更高的版本中使用jpm。</p>
+
+<p>本文为jpm参考。</p>
+</div>
+
+<p><span class="seoSummary"><a href="/en-US/Add-ons/SDK/Tools/cfx">cfx</a> 的Node版本允许你测试、运行以及打包扩展。</span></p>
+
+<p>你也可以阅读 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29">jpm教程</a> 开始学习。</p>
+
+<p>jpm 用法:</p>
+
+<pre class="brush: bash">jpm [command] [options]
+</pre>
+
+<p>jpm支持以下全局参数:</p>
+
+<pre class="brush: bash">-h, --help - 显示帮助信息并退出
+-V, --version - 打印出jpm版本号
+--addon-dir - 源代码目录,默认为当前目录
+</pre>
+
+<h2 id="安装">安装</h2>
+
+<p>jpm发布在node包管理器 <a class="external external-icon" href="https://www.npmjs.org/package/jpm">npm</a> 上。</p>
+
+<h3 id="安装npm">安装npm</h3>
+
+<p>有两种方法来获取npm。</p>
+
+<ul>
+ <li>访问 <a href="http://nodejs.org/">nodejs.org</a> 下载并安装Node.js。Node.js 包含npm。</li>
+ <li>或者,如果你的系统有像 APT 这种包管理器,就用它来安装。例如,在 Ubuntu 或者 Debian 的终端窗口里,输入<code>sudo apt-get install nodejs nodejs-legacy npm</code></li>
+</ul>
+
+<p>要测试安装是否成功,运行:</p>
+
+<pre class="brush: bash">​/usr/bin/env node -v</pre>
+
+<p>如果出现错误提示  <em>/usr/bin/env: node: No such file or directory</em> 并且你的 nodejs 是通过包管理的方式安装的,那你的 nodejs 很有可能安装为其它的名字。为了保证jpm的兼容,PATH之中必须是以node为可执行文件名的。在Debian和Ubuntu系统上,你可以通过安装兼容包nodejs-legacy来解决这个问题:</p>
+
+<pre class="brush: bash"><code>sudo apt-get install nodejs-legacy</code></pre>
+
+<p><font face="Consolas, Liberation Mono, Courier, monospace">在其它的发行版中,你或许必须手动创建一共本地符号链接:​</font></p>
+
+<pre><code>sudo ln -s "$(which nodejs)" /usr/local/bin/node</code></pre>
+
+<h3 id="安装jpm"><code>安装jpm</code></h3>
+
+<p>在你安装好npm并且将其加入你的PATH中后,你可以像安装其他npm包一样来安装jpm。</p>
+
+<h4 id="全局安装jpm">全局安装jpm</h4>
+
+<pre><code>npm install jpm --global</code></pre>
+
+<p>取决于你的安装,你可能需要管理员权限执行:</p>
+
+<pre class="brush: bash"><code>sudo npm install jpm --global</code></pre>
+
+<h4 id="局部安装jpm"><code>局部安装jpm</code></h4>
+
+<p><code>如果你不想,或者不能够全局安装jpm,你或许可以只为你安装它:</code></p>
+
+<pre><code>npm install jpm</code></pre>
+
+<p><code>在局部安装的情况下,为了在终端中运行jpm,你必须首先将目录</code>"$HOME/node_modules/.bin/"添加到你的终端PATH中。将下行中的命令添加到$HOME/.profile的末尾来实现永久添加(.profile将在每次运行一个新终端时被执行):</p>
+
+<pre><code>export PATH="$HOME/node_modules/.bin/:$PATH"</code></pre>
+
+<h4 id="通过git来安装jpm">通过git来安装jpm</h4>
+
+<p>另外,你也可以通过git安装jpm的最新版本</p>
+
+<pre>git clone https://github.com/mozilla-jetpack/jpm.git
+cd jpm
+npm install
+npm link
+</pre>
+
+<h3 id="jpm安装完毕后">jpm安装完毕后</h3>
+
+<p><span style="line-height: 1.5;">在全部搞定后,在命令行窗口中输入:</span></p>
+
+<pre class="brush: bash"><code>jpm</code></pre>
+
+<p>屏幕上显示了一系列可用的 jpm 命令。不同于 cfx,当在安装时使用了 --global 参数,你能在任何路径下启动的命令提示符中使用 jpm 命令。</p>
+
+<h3 id="还有问题?">还有问题?</h3>
+
+<p>如果你看不懂本文,要寻求帮助。SDK 用户和项目团队成员在<a class="external external-icon" href="http://groups.google.com/group/mozilla-labs-jetpack/topics">项目邮件列表</a>中讨论问题和建议。其他人也许会和你有一样的问题,所以试着搜索一下列表。也欢迎你发表一个新问题。你也可以在 <a class="external external-icon" href="http://irc.mozilla.org/">Mozilla 的 IRC 网络</a> 的 <a class="external external-icon" href="http://mibbit.com/?channel=%23jetpack&amp;server=irc.mozilla.org">#jetpack</a> 房间里和其他SDK的用户聊天。</p>
+
+<h2 id="命令参考">命令参考</h2>
+
+<p>有六个命令:</p>
+
+<table>
+ <tbody>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_init"><code>jpm init</code></a></td>
+ <td>创建一个基本的 add-on 作为你 add-on 的开端。</td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_run"><code>jpm run</code></a></td>
+ <td>运行一个带有你的 add-on 的 Firefox 实例。</td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_test"><code>jpm test</code></a></td>
+ <td>运行你插件的单元测试</td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_xpi"><code>jpm xpi</code></a></td>
+ <td>将你的插件打包为 <a href="https://developer.mozilla.org/zh-CN/docs/XPI">XPI</a> 文件(火狐的插件扩展文件名)</td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_post"><code>jpm post</code></a></td>
+ <td>把你的 add-on 打包成 <a href="https://developer.mozilla.org/zh-CN/docs/XPI">XPI</a> 文件,然后发送到某一个URL。</td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_watchpost"><code>jpm watchpost</code></a></td>
+ <td>无论是否有文件变更,把你的 add-on 打包成 <a href="https://developer.mozilla.org/zh-CN/docs/XPI">XPI</a> 文件发送到某一个URL。</td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_sign"><code>jpm sign</code></a></td>
+ <td>将你的插件打包为 <a href="https://developer.mozilla.org/zh-CN/docs/XPI">XPI</a> 文件并且取回一个由Mozilla签名的新XPI文件。</td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="jpm_init">jpm init</h3>
+
+<p>这个命令从头开始初始化一个新的 add-on。</p>
+
+<p>新建一个目录,转到该目录下,然后运行 <code>jpm init</code>。</p>
+
+<pre><code>mkdir my-addon
+cd my-addon
+jpm init</code></pre>
+
+<p>然后你会被要求提供关于你的 add-on 的一些信息:这会用来创建 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json">package.json</a> 文件。</p>
+
+<ul>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#title">title</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#name">name</a>: 默认是你运行 <code>jpm init 的目录名。除非</code>package.json里有 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#id"><code>id</code></a> 字段, jpm 在name前面加个<code>"@"</code>用作 <a href="https://developer.mozilla.org/en-US/Add-ons/Install_Manifests#id">add-on 安装清单的 <code>id</code> 字段</a>.</li>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#version">version</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#description">description</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#main">entry point</a> (映射向package.json中的 "main")</li>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#author">author</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#engines">engines</a> (支持哪些应用程序)</li>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#license">license</a></li>
+</ul>
+
+<p>大部分字段都有一个默认值,显示在那些问题的后面的括号里。如果你按了回车,那么你的 add-on 就用那个默认值。</p>
+
+<p>一旦你提供了一个值或者接受了默认值,你会看到"package.json"的完整内容,并被询问是否接受。</p>
+
+<p>然后 jpm 创建一个基本的 add-on,作为你开发的起点,文件结构如下:</p>
+
+<ul>
+ <li>my-addon
+ <ul>
+ <li>index.js</li>
+ <li>package.json</li>
+ <li>test
+ <ul>
+ <li>test-index.js</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+
+<h3 id="jpm_run">jpm run</h3>
+
+<p>此命令运行一个新的装有你的 add-on 的 Firefox实例:</p>
+
+<pre><code>jpm run</code></pre>
+
+<p><code>jpm run</code> 有以下选项:</p>
+
+<table>
+ <tbody>
+ <tr>
+ <td><code>-b --binary BINARY</code></td>
+ <td>
+ <p>指定二进制文件,使用该版本的火狐。可以用全路径,也可以用相对路径。</p>
+
+ <pre>
+<code>jpm run -b /path/to/Firefox/Nightly</code></pre>
+ 参看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Selecting_a_browser_version">选择浏览器版本</a>。</td>
+ </tr>
+ <tr>
+ <td><code>--binary-args CMDARGS</code></td>
+ <td>
+ <p>传递<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options">附件参数</a>到 Firefox。</p>
+
+ <p>例如,为了传递 <code>-jsconsole</code>参数给 Firefox 并打开<a href="https://developer.mozilla.org/en-US/docs/Tools/Browser_Console">浏览器</a>,试试下面命令:</p>
+
+ <pre>
+<code>jpm run --binary-args -jsconsole</code></pre>
+
+ <p>要传递多个参数,或者参数中间有空格,就把他们用引号括起来:</p>
+
+ <pre>
+<code>jpm run --binary-args '-url mzl.la -jsconsole'</code></pre>
+ </td>
+ </tr>
+ <tr>
+ <td><code>--debug</code></td>
+ <td>运行这个 add-on 的<a href="https://developer.mozilla.org/en-US/Add-ons/Add-on_Debugger">Add-on 调试器</a>。</td>
+ </tr>
+ <tr>
+ <td><code>-o --overload PATH</code></td>
+ <td>
+ <p>不再使用 Firefox 内建的 SDK 模块,使用指定 PATH 路径下的模块。如果加了 <code>-o</code> 但 PATH 没有指定,jpm 会寻找 JETPACK_ROOT 环境变量用作路径</p>
+
+ <p>参看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Overloading_the_built-in_modules">重载内建模块</a>以获取更多信息</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>-p --profile=<code> PROFILE</code></code></td>
+ <td>
+ <p>在你每次调用jpm run时,jpm 默认使用一个干净的临时的 Firefox <a href="http://support.mozilla.com/en-US/kb/profiles">配置文件(profile)</a>。使用<code>--profile</code> 选项以使得 jpm 使用已有的配置文件来打开 Firefox。</p>
+
+ <p>PROFILE的值可以是一个profile的名字或路径。</p>
+
+ <p>参看 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Using_profiles">使用 profile</a> 以获取更多信息。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>-v --verbose</code></td>
+ <td>(查看)详细操作</td>
+ </tr>
+ <tr>
+ <td><code>--no-copy</code></td>
+ <td>
+ <div class="warning">小心使用,因为 <code>jpm run|test</code> 会改变很多配置,不要和你的主配置文件一起使用。</div>
+
+ <div class="note">只有使用 <code>--profile</code> 的时候回生效</div>
+ 禁止配置文件的拷贝,允许重用配置。</td>
+ <td> </td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="jpm_test">jpm test</h3>
+
+<p>这个命令用来运行 add-on 的单元测试。命令:</p>
+
+<ul>
+ <li>查找在当前目录(或者 <code>--addon-dir</code> 目录)下的test文件夹。</li>
+ <li>打开所有名字以 "test-" 开头的文件。注意文件名中"test"后面的连字符号。<code>jpm test</code> 包含一个 "test-myCode.js" 文件,但会排除"test_myCode.js"或"test_myCode.js"。</li>
+ <li>调用文件中所有export的、以"test"开头的函数。</li>
+</ul>
+
+<pre><code>jpm test</code></pre>
+
+<p>查看 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Unit_testing">单元测试教程</a> 和 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/test_assert"> <code>assert</code> 模块参考文档</a>获取更多具体内容。</p>
+
+<p><code>jpm test</code> 接受一下选项:</p>
+
+<table>
+ <tbody>
+ <tr>
+ <td><code>-b --binary BINARY</code></td>
+ <td>
+ <p>指定所用 Firefox 的版本。BINARY 可被指定为绝对路径或者基于当前路径的相对路径。</p>
+
+ <pre>
+<code>jpm test -b /path/to/Firefox/Nightly</code></pre>
+
+ <p>请查看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Selecting_a_browser_version">选择一个浏览器版本</a>。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>--binary-args CMDARGS</code></td>
+ <td>
+ <p>传递<a href="http://kb.mozillazine.org/Command_line_arguments">附件参数</a>给 Firefox。</p>
+
+ <p>例如,传递 <code>-jsconsole</code> 参数,它会打开<a href="https://developer.mozilla.org/en-US/docs/Tools/Browser_Console">浏览器控制台</a>,试试下面的命令:</p>
+
+ <pre>
+<code>jpm test --binary-args -jsconsole</code></pre>
+
+ <p>传递多个参数,或者参数间有空格,请将它们用引号括起来:</p>
+
+ <pre>
+<code>jpm test --binary-args '-url mzl.la -jsconsole'</code></pre>
+ </td>
+ </tr>
+ <tr>
+ <td><code>--debug</code></td>
+ <td>运行 <a href="https://developer.mozilla.org/en-US/Add-ons/Add-on_Debugger">add-on debugger</a> 附件到当前 add-on 上。</td>
+ </tr>
+ <tr>
+ <td><code>-f --filter FILE[:TEST]</code></td>
+ <td>
+ <p>只运行名字和 FILE 匹配的测试文件,且名字匹配 TEST(可选)的测试函数。</p>
+
+ <pre>
+<code>jpm test --filter base64:btoa</code></pre>
+
+ <p>上面的命令值会运行名字中含有"base64"的文件,在这些文件中只会运行名字中含有"btoa"的测试函数。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>-o --overload PATH</code></td>
+ <td>
+ <p>不使用 Firefox 内建的模块,而使用 PATH 路径下的模块。如果 <code>-o</code> 指定而 PATH 被忽略,jpm会查找 JETPACK_ROOT 环境变量并将其用作路径。</p>
+
+ <p>查看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Overloading_the_built-in_modules">重载内建模块</a>以获取更多信息。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>-p --profile<code> PROFILE</code></code></td>
+ <td>
+ <p>你每次运行jpm call时,默认地,jpm使用一个干净的临时 Firefox <a href="http://support.mozilla.com/en-US/kb/profiles">配置文件</a>。使用<code>--profile</code> 选项来让 jpm 使用一个现有配置文件来打开火狐。</p>
+
+ <p>PROFILE 的值可以是配置文件的名称或者指向配置文件的路径。</p>
+
+ <p>查看<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Using_profiles">使用配置文件</a>来获取更多信息。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>--stop-on-error</code></td>
+ <td>
+ <p>即使测试失败,jpm test 默认还会继续运行测试。指定 <code>--stop-on-error</code> 的话,会在第一次失败后停止运行测试</p>
+
+ <pre>
+<code>jpm test --stop-on-error</code></pre>
+ </td>
+ </tr>
+ <tr>
+ <td><code>--tbpl</code></td>
+ <td>用<a href="https://treeherder.mozilla.org/">Treeherder</a> 格式打印 test 的输出</td>
+ </tr>
+ <tr>
+ <td><code>--times NUMBER</code></td>
+ <td>
+ <p>运行几遍 test:</p>
+
+ <pre>
+<code>jpm test --times 2</code></pre>
+ </td>
+ </tr>
+ <tr>
+ <td><code>-v --verbose</code></td>
+ <td>详细操作。</td>
+ </tr>
+ <tr>
+ <td><code>--no-copy</code></td>
+ <td>
+ <p>小心使用,因为 <code>jpm run|test</code> 会修改许多首选项,这些首选项在你的主配置文件中从未用过。</p>
+
+ <p>这仅仅在使用 <code>--profile</code> 时生效。</p>
+ 禁用配置未经的拷贝,允许用户重用配置文件。</td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="jpm_xpi">jpm xpi</h3>
+
+<p>这个命令将 add-on 打包为一个 <a href="https://developer.mozilla.org/en/XPI">XPI</a> 文件,这是 Mozilla 附加组件的安装文件的格式。</p>
+
+<pre><code>jpm xpi</code></pre>
+
+<p>它会在当前目录(或者 <code>--addon-dir</code> 指定的目录)查找 <code>package.json</code> 文件,并创建相关的 XPI 文件。它忽略任何 ZIP 或 XPI文件(译者注:OSX 上测试下来不会默认忽略这些文件,若要忽略请编辑.jpmignore文件),以及任何测试文件。它会包含其他所有文件。如果你想排除其他文件,查看 <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/SDK/Tools/en-US/Add-ons/SDK/Tools/jpmignore">.jpmignore 文件</a>。</p>
+
+<p>一旦你构建了一个 XPI 文件,你可以通过提交到 <a href="http://addons.mozilla.org/">addons.mozilla.org</a> 来分发你的附加组件。</p>
+
+<p><code>jpm xpi</code> 接受下列选项:</p>
+
+<table>
+ <tbody>
+ <tr>
+ <td><code>-v --verbose</code></td>
+ <td>
+ <p>打印详细操作:</p>
+
+ <pre>
+<code>jpm xpi -v</code></pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="jpm_post">jpm post</h3>
+
+<p>这个命令把附加组件打包为 <a href="https://developer.mozilla.org/en/XPI">XPI</a> 后 post 到某个URL。</p>
+
+<pre><code>jpm post</code></pre>
+
+<p>查找当前目录(或 <code>--addon-dir</code>)下的<code>package.json</code> 文件,创建 XPI 文件,post 到 <code>--post-url</code>。</p>
+
+<p><code>jpm post</code> 接受以下选项:</p>
+
+<table>
+ <tbody>
+ <tr>
+ <td><code>--post-url URL</code></td>
+ <td>
+ <p>创建 XPI 文件后,将扩展 post 到这个URL。</p>
+
+ <pre>
+<code>jpm post --post-url http://localhost:8888/</code></pre>
+
+ <p>查看<a href="https://www.npmjs.com/package/jpm#using-post-and-watchpost">使用 Post 和 Watchpost</a> 获取更多信息。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>-v --verbose</code></td>
+ <td>
+ <p>打印详细操作:</p>
+
+ <pre>
+<code>jpm post --post-url http://localhost:8888/ -v</code></pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="jpm_watchpost">jpm watchpost</h3>
+
+<p>这个命令在打包附件组件为 <a href="https://developer.mozilla.org/en/XPI">XPI</a> 文件后,无论文件是否改变都将其 post 到某个URL。</p>
+
+<pre><code>jpm watchpost</code></pre>
+
+<p>无论文件是否改变,在当前目录(或 <code>--addon-dir</code>)下创建一个 XPI并将其post到 <code>--post-url</code>。</p>
+
+<p><code>jpm watchpost</code> 接受以下选项:</p>
+
+<table>
+ <tbody>
+ <tr>
+ <td><code>--post-url URL</code></td>
+ <td>
+ <p>创建 XPI 文件后,将扩展 post 到这个URL。</p>
+
+ <pre>
+<code>jpm watchpost --post-url http://localhost:8888/</code></pre>
+
+ <p>查看 <a href="https://www.npmjs.com/package/jpm#using-post-and-watchpost">Using Post 和 Watchpost</a> 获取更多信息。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>-v --verbose</code></td>
+ <td>
+ <p>打印详细信息:</p>
+
+ <pre>
+<code>jpm watchpost --post-url http://localhost:8888/ -v</code></pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="jpm_sign">jpm sign</h3>
+
+<p>此特性仅从 jpm 1.0.4 起被支持。</p>
+
+<p>此命令为你的附加组件重新生成一个新的被Mozilla签名的 <a href="https://developer.mozilla.org/en-US/docs/XPI">XPI</a> 文件。这就允许你<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#Supporting_updates_for_self-hosted_add-ons">自己托管你的 add-on</a>,这样用户可以在安装时避免 <a href="https://wiki.mozilla.org/Add-ons/Extension_Signing">signed add-ons are required</a> 错误。在用这个命令之前,你需要<a href="https://addons.mozilla.org/en-US/developers/addon/api/key/">在 addons.mozilla.org 创建 API 证书</a>。</p>
+
+<p>你可以为你已经生成的 XPI 文件签名,就像如下,通过传递 XPI 文件给 <code>--xpi</code>参数:</p>
+
+<pre id="comment_text_2"><code>jpm sign --api-key ${AMO_API_KEY} --api-secret ${AMO_API_SECRET} --xpi &lt;xpi file&gt;</code></pre>
+
+<p>或者,你可以省略 <code>--xpi</code> 参数,这样 <code>jpm sign</code> 会从当前目录(或者 <code>--addon-dir</code>)生成一个XPI文件。</p>
+
+<pre><code>jpm sign --api-key ${AMO_API_KEY} --api-secret ${AMO_API_SECRET}</code></pre>
+
+<p>上面提交了一个 <a href="https://developer.mozilla.org/en-US/docs/XPI/">XPI</a> 到 <a href="https://addons.mozilla.org/">addons.mozilla.org</a> <a href="http://olympia.readthedocs.org/en/latest/topics/api/signing.html">签名g API</a>,如果通过验证,然后下载一个签名后的 XPI 文件到工作目录。</p>
+
+<p>下面是一些运行 <code>sign</code> 命令的结果:</p>
+
+<ul>
+ <li>你的 add-on 通过验证,被 Mozilla 签名,并且一个新的签名后的 <a href="https://developer.mozilla.org/en-US/docs/XPI">XPI</a> 文件被下载到你的工作目录。</li>
+ <li>你的 add-on 没有通过验证,没有签名,你获取到一个详细报告的链接。修复验证错误以后,你可以再次运行这个命令。</li>
+ <li>你的 add-on 公公验证,但是它不能自动签名,因为你的 add-on 是<a href="https://developer.mozilla.org/en-US/Add-ons/Distribution">列表上的</a>。列表上的 add-ons 需要人工复核才能被签名。</li>
+ <li>你的 add-on 已经存在某个版本号了,所以它没有被签名。增加 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json">package.json</a> 文件中的版本号并且再次运行命令。</li>
+</ul>
+
+<p>在底层,<code>jpm sign</code> 在<a href="https://addons.mozilla.org/">addons.mozilla.org</a>里创建了一个不会被列出的附加组件,这就意味着你必须自己把XPI文件分发给你的用户来安装。如果你需要创建一个在列表中的附加组件,只要<a href="https://addons.mozilla.org/en-US/developers/addon/submit/2">直接将它提交到 addons.mozilla.org</a>,在那里它自动会被签名。如果你在安装一个已签名的附加组件时遇到困难,参看<a href="https://developer.mozilla.org/en-US/docs/Extension_Versioning%2C_Update_and_Compatibility#Debugging_and_solving_problems">调试</a>一节。</p>
+
+<p><code>jpm sign</code> 接收以下参数:</p>
+
+<table>
+ <tbody>
+ <tr>
+ <td><code>--api-key=API_KEY</code></td>
+ <td>
+ <p><a href="https://addons.mozilla.org/en-US/developers/addon/api/key/">addons.mozilla.org key管理页面</a>生成的API访问key(字符串)。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>--api-secret=API_SECRET</code></td>
+ <td>
+ <p><a href="https://addons.mozilla.org/en-US/developers/addon/api/key/">addons.mozilla.org key 管理页面</a>生成的API访问密钥(字符串)。这个值应该被小心保密并且永远不要记录到版本控制中。如果你的密钥被破解,另一个开发者就能上传附加组件到你的账号上。你应该立即撤销泄露的API证书并且重新生成一份。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>--api-url-prefix=http://.../api</code></td>
+ <td>
+ <p>可选的API URL前缀,如果你想使用一个试用签名的API。</p>
+
+ <p>例如,你可以通过<code>https://addons-dev.allizom.org/api/v3</code>的认证来使用<a href="https://addons.mozilla.org/">addons.mozilla.org</a>的开发者版本。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>--xpi=/path/to/file.xpi</code></td>
+ <td>
+ <p>需要签名的<a href="https://developer.mozilla.org/en-US/docs/XPI">XPI</a>文件。如果没指定文件,一个新的XPI会在当前目录(或者<code>--addon-dir</code>)中生成。</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="一些技巧">一些技巧</h2>
+
+<h3 id="选择浏览器版本">选择浏览器版本</h3>
+
+<p>默认地,<code>jpm run</code> 和 <code>jpm test</code> 运行 release 版本的 FireFox。你可以有一两种办法来告诉 jpm 使用一个不同的版本:</p>
+
+<ul>
+ <li>
+ <p>你可以使用 <code>-b</code> 或者 <code>--binary</code> 选项来告诉 jpm 去使用一个不同版本的 Firefox。你可以提供一个指定二进制文件的路径:</p>
+
+ <pre><code>jpm run -b /path/to/Firefox/Nightly</code></pre>
+
+ <p>有个简化的方法,你可以传递"nightly"、"aurora"、"beta"或者"firefox"然后jpm会在默认位置寻找这些 Firefox 的版本:</p>
+
+ <pre><code>jpm run -b nightly</code></pre>
+ </li>
+ <li>
+ <p>你可以设置 <code>JPM_FIREFOX_BINARY</code> 环境变量为你想运行的 Firefox 版本的路径。在你调用 <code>jpm run</code> 或 <code>jpm test</code> 而不带 <code>-b</code> 选项时,jpm 首先检查 <code>JPM_FIREFOX_BINARY</code>,并且将其当做已设置的路径来用。</p>
+ </li>
+</ul>
+
+<h3 id="使用_.jpmignore_来忽略文件">使用 <code>.jpmignore</code> 来忽略文件</h3>
+
+<p>使用 <code>.jpmignore</code> 就像使用 <code>git</code> 的<code>.gitignore</code>,Mercurial 的 <code>.hgignore</code>,或者 npm 的 <code>.npmignore</code>。通过使用这个文件,你可以在使用 <code>jpm xpi</code> 编译 <code>.xpi</code> 文件时,让 <code>jpm</code> 知道你想要忽略哪些文件。</p>
+
+<p>这是个例子:</p>
+
+<pre><code># Ignore .DS_Store files created by mac
+.DS_Store
+
+# Ignore any zip or xpi files
+*.zip
+*.xpi</code></pre>
+
+<p>有着以上内容的 <code>.jpmignore</code> 文件会忽略所有的 zip 文件和 <code>.DS_Store</code> 文件,这些文件不会包括在 <code>jpm xpi</code> 所生成的 xpi 文件中。</p>
+
+<h3 id="使用配置"><a name="Using_profiles">使用配置</a></h3>
+
+<p>默认地,<code>jpm run</code> 每次都会使用一个新的配置。这就意味着前一次运行 <code>jpm</code> 时的任何配置,默认都不会在下一次中使用。</p>
+
+<p>这其中包括,比如你安装的任何附加组件,或者你的历史记录,或者任何使用 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/simple-storage">simple-storage</a> API 存储的数据。</p>
+
+<p>为了让 <code>jpm</code> 使用一个特定的配置,传递 <code>--profile</code> 选项,设定你想使用的配置文件的名字,或者是配置文件的路径。</p>
+
+<pre><code>jpm run --profile boogaloo</code></pre>
+
+<pre><code>jpm run --profile path/to/boogaloo</code></pre>
+
+<p>如果你提供了 <code>--profile</code> 但是它的参数不是一个已有配置文件的名字或路径,jpm 会打开 <a href="https://support.mozilla.org/en-US/kb/profile-manager-create-and-remove-firefox-profiles">配置文件管理器</a> 让你选择一个已有的配置文件或者创建一个新的配置文件:</p>
+
+<pre><code>jpm run --profile i-dont-exist</code></pre>
+
+<h3 id="开发时不用重启浏览器">开发时不用重启浏览器</h3>
+
+<p>因为每次调用 <code>jpm run</code> 时都会重启浏览,如果你十分频繁地修改附加组件,这就可能有点笨重了。一个替代的开发模型是使用 <a href="https://addons.mozilla.org/en-US/firefox/addon/autoinstaller/" rel="noreferrer">扩展自动安装器</a>附加组件:它会在特定端口监听新 XPI 文件并且自动安装它们。这样,你就能测试新的改动,而不用重启浏览器:</p>
+
+<ul>
+ <li>修改附件组件</li>
+ <li>运行 <code>jpm post --post-url http://localhost:8888/</code>,来创建 XPI 文件并提交。</li>
+</ul>
+
+<p>你甚至可以用一个简单的脚本来自动化这一工作流程。例如:</p>
+
+<pre><code>jpm watchpost --post-url http://localhost:8888/</code></pre>
+
+<p>注意,比起使用 <code>jpm run</code> 运行附加组件时的日志级别,你在使用这个方法时控制台定义的日志级别是不一样的。这意味着,如果你想看到 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tutorials/Logging" rel="noreferrer"><code>console.log()</code></a> 消息的输出,你必须微调一下配置。查看 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/console#Logging_Levels" rel="noreferrer">logging levels</a> 文档以获取这方面的详细信息。</p>
+
+<h3 id="重载内建模块">重载内建模块</h3>
+
+<p>你用来实现你的附加组件的SDK模快是 Firefox 内建的。当你使用 <code>jpm run</code> 或 <code>jpm xpi</code> 来运行或者打包附加组件时,附加组件使用其所在的 Firefox 版本中的模块版本。</p>
+
+<p>作为附件组件开发者,这一般就是你想要的。但是如果你在开发 SDK 模块本身,这就不合适了。这时你需要:</p>
+
+<ul>
+ <li>获取你想要的 SDK 模块的本地拷贝:一般来说就是从 <a href="https://github.com/mozilla/addon-sdk" rel="noreferrer">GitHub 仓库</a>中检出SDK。</li>
+ <li>设置 <code>JETPACK_ROOT</code> 环境变量,指向你的本地拷贝</li>
+ <li>传递 <code>-o</code> 选项到 <code>jpm run</code> 或 <code>jpm xpi</code>:</li>
+</ul>
+
+<pre><code>jpm run -o</code></pre>
+
+<p>这会通知 jpm 去使用 SDK 模块的本地拷贝,而不是 Firefox 内部的模块。如果你不想设置 <code>JETPACK_ROOT</code> 环境变量,你可以使用 <code>-o</code> 传递SDK模块本地拷贝的位置:</p>
+
+<pre><code>jpm run -o "/path/to/addon-sdk/"</code></pre>
+
+<p>路径必须是一个绝对路径并且指向 SDK 的根目录(不是 addon-sdk/sdk 或 addon-sdk/sdk/lib)。</p>
+
+<h3 id="支持自托管附加组件的更新">支持自托管附加组件的更新</h3>
+
+<p>此特性仅被 jpm 1.0.3 及之后版本支持,</p>
+
+<p>当你给你的附加组件来添加特性或者修复 bug 时,你想让之前安装好的附加组件将自己从老版本更新到新版本。</p>
+
+<p>如果你在 <a href="https://addons.mozilla.org/">addons.mozilla.org</a> 上列出你的附加组件,那么你要做的只是提交一个新的版本;附加组件默认会检查它们在 <a href="https://addons.mozilla.org/">addons.mozilla.org</a> 上的新版本。好了,你不用继续往下看这一节了。</p>
+
+<p>如果你没有在 <a href="https://addons.mozilla.org/">addons.mozilla.org</a> 上列出你的附加组件,你需要生成一个 Mozilla 签名的 XPI 文件并告诉 Firefox 哪里可以找到这个附加组件的新版本。方法就是:</p>
+
+<ul>
+ <li>每次你想要创建一个新版本时,你运行 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_sign">jpm sign</a></li>
+ <li>当你需要更新时,更新由你托管的签名好的附加组件</li>
+ <li>你维护一个“更新清单”,包含了指向那个 XPI 的URL</li>
+ <li>你的附加组件告诉 Firefox 哪里可以找到更新清单</li>
+</ul>
+
+<p>为了达到这个目的,package.json中需要包含两个额外的key :</p>
+
+<ul>
+ <li><code><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#updateURL">updateURL</a></code>:这个 URL 包含在 <code>jpm xpi</code> 所编译的 XPI 文件的<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/Install_Manifests">安装清单</a>中。他指向了你的更新清单。<code>updateURL</code> 值<em>可以</em>是HTTPS的。如果不是,那么你也可以签名的更新清单,并且使用 package.json 文件中的 <code><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#updateKey">updateKey</a></code> 字段来包含其公钥。参看 <a href="https://developer.mozilla.org/en-US/docs/Extension_Versioning%2C_Update_and_Compatibility#Securing_Updates">安全地更新</a> 以获取这方面更多信息</li>
+ <li><code><a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/package_json#updateLink">updateLink</a></code>:这个 URL 包含在那个更新清单文件中。它指向了 XPI,并且<em>必须</em>是一个 HTTPS URL。</li>
+</ul>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/11847/addons-update.svg" title="[https://mdn.mozillademos.org]"></p>
+
+<p>如果你设置了 <code>updateURL</code> 和 <code>updateLink</code>(如果 <code>updateKey</code> 不是 HTTPS 的,那也要包括 <code>updateKey</code>),那么 <code>jpm xpi</code> 会:</p>
+
+<ul>
+ <li>生成 XPI 文件时将 <code>updateURL</code> 设置为你提供的值。</li>
+ <li>和 XPI 文件一起,生成更新清单,并将清单中的 <code>updateURL</code> 设置为你提供的值。</li>
+</ul>
+
+<p>然后你将更新清单托管到 <code>updateURL</code>,并且将新版 XPI 托管到 <code>updateLink</code>。</p>
+
+<p>获取更多这方面的详细信息,参看<a href="https://developer.mozilla.org/en-US/docs/Extension_Versioning,_Update_and_Compatibility#Automatic_Add-on_Update_Checking">自动检查附件组件更新</a>。</p>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tools/package_json/index.html b/files/zh-cn/mozilla/add-ons/sdk/tools/package_json/index.html
new file mode 100644
index 0000000000..cd08ff2b64
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tools/package_json/index.html
@@ -0,0 +1,312 @@
+---
+title: package.json
+slug: Mozilla/Add-ons/SDK/Tools/package_json
+translation_of: Archive/Add-ons/Add-on_SDK/Tools/package_json
+---
+<p>{{AddonSidebar}}</p>
+
+<p><span class="seoSummary">The <code>package.json</code> file contains manifest data for your add-on, providing not only descriptive information about the add-on for presentation in the Add-ons Manager, but other metadata required of add-ons.</span></p>
+
+<p>一些条目, 比如<a href="/en-US/Add-ons/SDK/Tools/package_json#icon"><code>icon</code></a>, <a href="/en-US/Add-ons/SDK/Tools/package_json#name"><code>name</code></a>和<a href="/en-US/Add-ons/SDK/Tools/package_json#description"><code>description</code></a>, 有类似<a href="https://developer.mozilla.org/en-US/docs/Install_Manifests">install manifest</a>的格式, 并且<code>package.json会写入</code>install manifest, 当使用<a href="/en-US/Add-ons/SDK/Tools/jpm#jpm_xpi"><code>jpm xpi</code></a><code>的时候.</code></p>
+
+<p>Others, such as <a href="/en-US/Add-ons/SDK/Tools/package_json#lib"><code>lib</code></a>, <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions"><code>permissions</code></a>, and <a href="/en-US/Add-ons/SDK/Tools/package_json#preferences"><code>preferences</code></a>, represent instructions to the <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a> tool itself to generate and include particular code and data structures in your add-on.</p>
+
+<p>其他如<a href="/en-US/Add-ons/SDK/Tools/package_json#lib"><code>lib</code></a>, <a href="/en-US/Add-ons/SDK/Tools/package_json#permissions"><code>permissions</code></a>和<a href="/en-US/Add-ons/SDK/Tools/package_json#preferences"><code>preferences</code></a>表示使用<a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>工具的步骤, 生成你扩展包含的特殊代码和数据结构.</p>
+
+<h2 id="创建manifest">创建manifest</h2>
+
+<p><code>package.json起初是通过运行</code><a href="/en-US/Add-ons/SDK/Tools/jpm#jpm_init"><code>jpm init</code></a>生成的<code>,通常在扩展的根目录.比如下面(假设扩展目录是</code>"my-addon"<code>)</code></p>
+
+<pre class="brush: json">{
+ "name": "my-addon",
+ "title": "my-addon",
+  "id": "jid1-1FERGV45e4f4f",
+ "description": "a basic add-on",
+ "author": "",
+ "license": "MPL-2.0",
+ "version": "0.1"
+}</pre>
+
+<p>如果你使用新的<a href="/en-US/Add-ons/SDK/Tools/jpm">jpm tool</a>话,可以方便的从package.json获取manifest数据, 通过require其他模块的方式:</p>
+
+<pre class="brush: js" id="comment_text_1">var title = require("./package.json").title;</pre>
+
+<h2 id="Key_reference">Key reference</h2>
+
+<p><code>package.json</code> may contain the following keys:</p>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td id="author"><code>author</code></td>
+ <td>
+ <p>The name of the package's original author; this could be the name of a person or a company. Defaults to an empty string. It may include a optional URL in parentheses and an email address in angle brackets.</p>
+
+ <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#creator"><code>em:creator</code></a> element in the <code>install.rdf</code> file generated by <code>cfx</code>.</p>
+
+ <div class="note"><strong>Note:</strong> <a href="https://developer.mozilla.org/Add-ons/SDK/Tools/jpm">jpm</a> supports <a href="https://docs.npmjs.com/files/package.json#people-fields-author-contributors">NodeJS people fields</a>.</div>
+ </td>
+ </tr>
+ <tr>
+ <td id="contributors"><code>contributors</code></td>
+ <td>
+ <p>An array of additional <a href="/en-US/Add-ons/SDK/Tools/package_json#author"><code>author</code></a> strings, identifying other contributors to the add-on.</p>
+
+ <p>These values will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#contributor"><code>em:contributor</code></a> elements in its <code>install.rdf</code>.</p>
+
+ <div class="note"><strong>Note:</strong> This is deprecated along with <code>cfx</code>; it's not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</div>
+ </td>
+ </tr>
+ <tr>
+ <td id="dependencies"><code>dependencies</code></td>
+ <td>
+ <p>A string or an array of strings specifying the names of packages that this add-on requires in order to function properly.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="description"><code>description</code></td>
+ <td>
+ <p>The add-on's description; this is a human-readable message describing what the add-on does. This defaults to the text "a basic add-on".</p>
+
+ <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#description"><code>em:description</code></a> element in its <code>install.rdf</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="engines"><code>engines</code></td>
+ <td>
+ <p>Object with supported applications (key) and required version numbers (value).</p>
+
+ <ul>
+ <li><code>firefox</code>: Firefox Desktop</li>
+ <li><code>fennec</code>: Firefox for Android</li>
+ </ul>
+
+ <p>Example:</p>
+
+ <pre>
+<code> "engines": {
+ "firefox": "&gt;=38.0a1",
+ "fennec": "&gt;=38.0a1"
+ }</code></pre>
+ </td>
+ </tr>
+ <tr>
+ <td id="fullName"><code>fullName</code> {{deprecated_inline}}</td>
+ <td>
+ <div class="note"><strong>Note:</strong> This is deprecated along with <code>cfx</code>; it's not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</div>
+
+ <p>The full name of the package. It can contain spaces.</p>
+
+ <p>If this key is present its value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#name"><code>em:name</code></a> element in its <code>install.rdf</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="harnessClassID"><code>harnessClassID</code> {{deprecated_inline}}</td>
+ <td>
+ <div class="note"><strong>Note:</strong> This is deprecated along with <code>cfx</code>; it's not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</div>
+
+ <p>String in the <a href="https://developer.mozilla.org/en-US/docs/Generating_GUIDs">GUID format</a>.</p>
+
+ <p>This is used as a <a href="https://developer.mozilla.org/en-US/docs/Creating_XPCOM_Components/An_Overview_of_XPCOM#CID"><code>classID</code></a> of the "harness service" XPCOM component. Defaults to a random GUID generated by <code>cfx</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="homepage"><code>homepage</code></td>
+ <td>
+ <p>The URL of the add-on's website.</p>
+
+ <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#homepageURL"><code>em:homepageURL</code></a> element in its <code>install.rdf</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="icon"><code>icon</code></td>
+ <td>
+ <p>The path to an image file containing the icon for the add-on. Defaults to <code>icon.png</code>. If no icon is specified, the standard add-on icon will be used by default.</p>
+
+ <div class="warning">
+ <p>When using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>, relative path to the data directory (to make it re-usable for add-on HTML content) does not currently work. Instead you have to use following syntax:</p>
+
+ <p>resource://ID/data/icon-name.png</p>
+
+ <p>ID is the value from the <code>id </code>field. If it does <strong>not</strong> begin with the <code>@</code>-character, then <code>@</code> has to be escaped as <code>-at-</code> and <code>.</code> as <code>-dot-</code>. If the ID is a GUID, the curly braces used in the <code>id</code> field are <strong>not</strong> included.</p>
+ </div>
+
+ <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#iconURL"><code>em:iconURL</code></a> element in its <code>install.rdf</code>.</p>
+
+ <p>The icon may be up to 48x48 pixels in size (although a bigger icon is tolerated here too)</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="icon64"><code>icon64</code> {{deprecated_inline}}</td>
+ <td>
+ <div class="note">
+ <p><strong>Note:</strong> This is deprecated along with <code>cfx</code>; it's not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p>
+ </div>
+
+ <p><span style="background-color: rgba(212, 221, 228, 0.14902);">The path to an image</span> containing the large icon for the add-on. Defaults to <code>icon64.png</code>. If you don't provide an icon here, the same icon as specified by <code>icon</code> will be used.</p>
+
+ <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#icon64URL"><code>em:icon64URL</code></a> element in its <code>install.rdf</code>.</p>
+
+ <p>The icon may be up to 64x64 pixels in size.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="id"><code>id</code></td>
+ <td>
+ <p>A globally unique identifier for the add-on.</p>
+
+ <p>This value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#id"><code>em:id</code></a> element in its <code>install.rdf</code>.</p>
+
+ <p>See the <a href="/en-US/Add-ons/SDK/Guides/Program_ID">Program ID documentation</a>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>lib</code></td>
+ <td>
+ <p>String representing the top-level module directory provided in this add-on. Defaults to "lib".</p>
+
+ <div class="note">
+ <p><strong>Note:</strong> This is deprecated along with <code>cfx</code> and is not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td id="license"><code>license</code></td>
+ <td>
+ <p>The name of the license under which the add-on is distributed, with an optional URL in parentheses. Defaults to <code>"MPL-2.0"</code>.</p>
+
+ <div class="note">
+ <p><strong>Note</strong>: It is recommend that you use an <a href="https://spdx.org/licenses/">SPDX license ID</a>.</p>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td id="main"><code>main</code></td>
+ <td>
+ <p>A string representing the name of a program module that is located in one of the top-level module directories specified by <a href="/en-US/Add-ons/SDK/Tools/package_json#lib"><code>lib</code></a>. Defaults to <code>"main"</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="name"><code>name</code></td>
+ <td>
+ <p>The add-on's name. This name cannot contain spaces or periods, and defaults to the name of the parent directory.</p>
+
+ <p>When the add-on is built as an XPI, if the <a href="/en-US/Add-ons/SDK/Tools/package_json#fullName"><code>fullName</code></a> and <a href="/en-US/Add-ons/SDK/Tools/package_json#title"><code>title</code></a> keys are not present, <code>name</code> is used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#name"><code>em:name</code></a> element in its <code>install.rdf</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="packages"><code>packages</code></td>
+ <td>
+ <div class="note">
+ <p><strong>Note:</strong> This is deprecated along with <code>cfx</code> and is not available when using <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p>
+ </div>
+
+ <p>A string pointing to a directory containing additional packages. Defaults to <code>"packages"</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="permissions"><code>permissions</code></td>
+ <td>
+ <p>A set of permissions that the add-on needs.</p>
+
+ <p><strong><code>private-browsing</code></strong>: a boolean indicating whether or not the add-on supports private browsing. If this value is not <code>true</code> or is omitted, then the add-on will not see any private windows or objects, such as tabs, that are associated with private windows. See the documentation for the <a href="/en-US/Add-ons/SDK/High-Level_APIs/private-browsing"><code>private-browsing</code> module</a>.</p>
+
+ <p><strong><code>cross-domain-content</code></strong>: a list of domains for which content scripts are given cross-domain privileges to access content in iframes or to make XMLHTTPRequests. See the documentation for <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts/Cross_Domain_Content_Scripts">enabling cross-domain content scripts</a>.</p>
+
+ <p><strong><code>multiprocess</code></strong>: a Boolean value declaring whether this add-on is, or is not, compatible with <a href="/en-US/Add-ons/Working_with_multiprocess_Firefox">multiprocess Firefox</a>.</p>
+
+ <div class="note">
+ <p><strong>Note</strong> the <code>multiprocess</code> permission is not supported by <a href="/en-US/Add-ons/SDK/Tools/cfx">cfx</a>.</p>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td id="preferences"><code>preferences</code></td>
+ <td>
+ <p>An array of <a href="/en-US/docs/Glossary/JSON">JSON</a> objects that use the following keys: <code>name</code>,<code>type</code>, <code>value</code>, <code>title</code>, and <code>description</code>. These JSON objects will be used to create a preferences interface for the add-on in the Add-ons Manager.</p>
+
+ <p>See the documentation for the <a href="/en-US/Add-ons/SDK/High-Level_APIs/simple-prefs"><code>simple-prefs</code> module</a>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="preferences-branch"><code>preferences-branch</code></td>
+ <td>Use this to specify an alternative branch for your add-on's simple-prefs. See <a href="/en-US/Add-ons/SDK/High-Level_APIs/simple-prefs#Simple-prefs_in_the_preferences_system">"Simple-prefs in the preferences system"</a> for more details.</td>
+ </tr>
+ <tr>
+ <td id="title"><code>title</code></td>
+ <td>
+ <p>The human-readable title of the package; this can contain spaces.</p>
+
+ <p>If this key is present its value will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#name"><code>em:name</code></a> element in its <code>install.rdf</code>.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="translators"><code>translators</code></td>
+ <td>
+ <p>An array of strings listing the people who contributed to the localization of this add-on.</p>
+
+ <p>These values will be used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#translator"><code>em:translator</code></a> elements in its <code>install.rdf</code>.</p>
+
+ <div class="note"><strong>Note:</strong> <a href="https://developer.mozilla.org/Add-ons/SDK/Tools/jpm">jpm</a> supports <a href="https://docs.npmjs.com/files/package.json#people-fields-author-contributors">NodeJS people fields</a>.</div>
+ </td>
+ </tr>
+ <tr>
+ <td id="unpack"><code>unpack</code></td>
+ <td>
+ <p>Same as the <code><a href="/en-US/Add-ons/Install_Manifests#unpack">unpack</a></code> in an <code>install.rdf</code> file.</p>
+
+ <p>Useful when the extension contains binaries.</p>
+ </td>
+ </tr>
+ <tr>
+ <td id="updateKey"><code>updateKey</code></td>
+ <td>
+ <p>Same as the <code><a href="/en-US/Add-ons/Install_Manifests#updateKey">updateKey</a></code> in an <code>install.rdf</code> file.</p>
+
+ <p>See <a href="/en-US/Add-ons/SDK/Tools/jpm#Supporting_updates_for_self-hosted_add-ons">Supporting updates for self-hosted add-ons</a>.</p>
+
+ <div class="note">
+ <p><strong>Note:</strong> This key is only available with <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td id="updateLink"><code>updateLink</code></td>
+ <td>
+ <p>Same as the <code><a href="/en-US/docs/Extension_Versioning%2C_Update_and_Compatibility#Securing_Updates">updateLink</a></code> for an <code>update.rdf</code> file. Previously was <code><a href="/en-US/Add-ons/SDK/Tools/cfx#updateURL_and_updateLink">--update-link in cfx</a></code>.</p>
+
+ <p>See <a href="/en-US/Add-ons/SDK/Tools/jpm#Supporting_updates_for_self-hosted_add-ons">Supporting updates for self-hosted add-ons</a>.</p>
+
+ <div class="note">
+ <p><strong>Note:</strong> This key is only available with <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td id="updateURL"><code>updateURL</code></td>
+ <td>
+ <p>Same as the <code><a href="/en-US/Add-ons/Install_Manifests#updateURL">updateURL</a></code> for an <code>install.rdf</code> file.</p>
+
+ <p>See <a href="/en-US/Add-ons/SDK/Tools/jpm#Supporting_updates_for_self-hosted_add-ons">Supporting updates for self-hosted add-ons</a>.</p>
+
+ <div class="note">
+ <p><strong>Note:</strong> This key is only available with <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a>.</p>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td id="version"><code>version</code></td>
+ <td>
+ <p>String representing the version of the add-on. Defaults to "0.0.1".</p>
+
+ <p>This value is used as the add-on's <a href="https://developer.mozilla.org/en-US/docs/Install_Manifests#version"><code>em:version</code></a> element in its <code>install.rdf</code>.</p>
+
+ <div class="note">
+ <p><strong>Note:</strong> For <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a> the version must be a valid <a href="http://semver.org/">semver</a>.</p>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/add_a_menu_item_to_firefox/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/add_a_menu_item_to_firefox/index.html
new file mode 100644
index 0000000000..29348bbabb
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/add_a_menu_item_to_firefox/index.html
@@ -0,0 +1,92 @@
+---
+title: Add a Menu Item to Firefox
+slug: Mozilla/Add-ons/SDK/Tutorials/Add_a_Menu_Item_to_Firefox
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Add_a_Menu_Item_to_Firefox
+---
+<div class="note">
+ <p>学习本模块你需要 <a href="/en-US/Add-ons/SDK/Installation">安装SDK</a> 学习基础工具<a href="/en-US/Add-ons/SDK/Getting_Started_With_cfx"><code>cfx</code></a>.</p>
+</div>
+<div class="note">
+ <p>如果你使用 <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a> 替代cfx, 使用第三方模块的方式是不同的, 你应该阅读 <a href="/en-US/Add-ons/SDK/Tutorials/Using_third-party_modules_%28jpm%29">jpm</a>的相应版本替代本教程.</p>
+ <p>给予Python可能未来废弃,使用JPM基于nodejs(译者备注).</p>
+</div>
+<p class="ordinary-output target-output"><span>SDK还不能为<span>火狐浏览器</span>提供一个API添加新的菜单项。</span><span>但它是可扩展的设计,所以任何人都可以建立和发布模块,使用插件开发者。</span><span>幸运的是</span><span>,</span><span>埃里克</span><span>沃尔德</span><span>写的</span><a href="https://github.com/mykmelez/menuitems-jplib"><span>MenuItems</span></a><span>模块,</span><span>能够使我们</span><span>添加菜单项</span><span>。</span></p>
+<p class="ordinary-output target-output"><span>本教程有双重的责任。</span><span>它描述的一般</span><span>方法,</span><span>使用一个外部的</span><span>,</span><span>在你的</span><span>插件</span><span>的第三方</span><span>模块</span><span>,</span><span>并</span><span>描述了如何</span><span>使用</span><span>特别的</span><span>MenuItems</span><span>模块</span><span>添加一个菜单项</span><span>。</span></p>
+<p class="ordinary-output target-output"><span>首先,创建一个新的扩展程序。</span><span>创建一个</span><span>目录名称为</span><span>“</span><span>clickme</span><span>”</span><span>(名称随意)</span><span>,</span><span>找到它并运行</span><code>cfx init</code><span>初始化</span><span>。</span></p>
+<pre>mkdir clickme
+cd clickme
+cfx init
+</pre>
+<p>通常将创建目录结构:</p>
+<ul>
+ <li>clickme
+ <ul>
+ <li>data</li>
+ <li>docs
+ <ul>
+ <li>main.md</li>
+ </ul>
+ </li>
+ <li>lib
+ <ul>
+ <li>main.js</li>
+ </ul>
+ </li>
+ <li>package.json</li>
+ <li>README.md</li>
+ <li>tests
+ <ul>
+ <li>test-main.js</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+<div>
+  </div>
+<h2 id="安装_menuitems"><code>安装 menuitems</code></h2>
+<p>在 "clickme"下创建一个名称为"packages"的目录. 从 <a href="https://github.com/mykmelez/menuitems-jplib/zipball/4d6ae5b410d79cc16c9c76920fbaa8a367e44ca7">https://github.com/mykmelez/menuitems-jplib</a>  下载 <code>menuitems 并展开到刚才创建的</code>"packages" 目录下:</p>
+<pre>mkdir packages
+cd packages
+tar -xf ../erikvold-menuitems-jplib-d80630c.zip
+</pre>
+<h2 id="模块依赖">模块依赖</h2>
+<p class="ordinary-output target-output"><span>如果</span><span>第三方模块</span><span>只</span><span>取决于</span><span>SDK</span><span>模块</span><span>,</span><span>你</span><span>可以马上</span><span>使用它们</span><span>,</span><span>但如果</span><span>他们依赖于其他</span><span>第三方模块</span><span>,</span><span>你需要安装</span><span>的</span><span>依赖</span><span>以及</span><span>。</span></p>
+<p><span class="high-light-bg">在软件包的主目录,你会发现一个叫做</span> "package.json"的文件.  <span>打开它,看看一个</span>名称"dependencies"的入口.  <code>menuitems</code> 包的入口:</p>
+<pre>"dependencies": ["vold-utils"]
+</pre>
+<p>这告诉我们需要安装 <code>vold-utils</code> 包, 我们可以从<a href="https://github.com/mykmelez/vold-utils-jplib/zipball/a321447dc5d613df33023165854957c181dc3174">https://github.com/mykmelez/vold-utils-jplib</a> 下载,并添加到 <code>packages</code> 目录<code>下的旁边的menuitems</code>.</p>
+<h2 id="使用menuitems"><code>使用menuitems</code></h2>
+<p> <a href="https://github.com/mykmelez/menuitems-jplib/blob/master/docs/menuitems.md"><code>Menuitems</code>模块文档</a> <code>告诉使用MenuItem()创建一个新的菜单项</code>. <code>MenuItem()可接受的附加选项</code>, 我们将使用最迷你的配置:</p>
+<ul>
+ <li><code>id</code>: 菜单项标示符</li>
+ <li><code>label</code>:菜单项线上的文本</li>
+ <li><code>command</code>: 用户选择菜单项的响应函数</li>
+ <li><code>menuid</code>: 菜单项的父类标示符</li>
+ <li><code>insertbefore</code>: 我们希望出现的标示符之前的位置</li>
+</ul>
+<div>
+ <div>
+ <pre class="brush: js">var menuitem = require("menuitems").Menuitem({
+ id: "clickme",
+ menuid: "menu_ToolsPopup",
+ label: "Click Me!",
+ onCommand: function() {
+ console.log("clicked");
+ },
+ insertbefore: "menu_pageInfo"
+});</pre>
+ <div>
+  </div>
+ </div>
+</div>
+<p>接下来, 我们将<code>声明menuitems</code>的依赖包. 在你的add-on's <code>package.json文件添加一行</code>:</p>
+<pre>"dependencies": "menuitems"
+</pre>
+<p>Note that due to <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=663480">bug 663480</a>, if you add a <code>dependencies</code> line to <code>package.json</code>, and you use any modules from the SDK, then you must also declare your dependency on that built-in package, like this:</p>
+<pre>"dependencies": ["menuitems", "addon-sdk"]
+</pre>
+<p class="ordinary-output target-output"><span>现在我们要做的。</span><span>运行</span><span>插件</span><span>,</span><span>你会</span><span>看到新的项目</span><span>出现在工具</span><span>菜单:</span><span>选择它,</span><span>你会看到</span><code>info: clicked </code><span>出现在</span><span>控制台</span><span>。</span></p>
+<h2 id="Caveats">Caveats</h2>
+<p class="ordinary-output target-output"><span>第三方</span><span>模块</span><span>使用</span><span>不直接支持的</span><span>SDK功能</span><span>的好方法,</span><span>但由于</span><span>第三方模块</span><span>通常使用</span><span>低级别的</span><span>API</span><span>,</span><span>它们可以通过</span><span>Firefox的</span><span>新版本</span><span>了</span><span>。</span></p>
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/adding_a_button_to_the_toolbar/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/adding_a_button_to_the_toolbar/index.html
new file mode 100644
index 0000000000..8e4438f818
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/adding_a_button_to_the_toolbar/index.html
@@ -0,0 +1,83 @@
+---
+title: 在工具栏上添加按钮
+slug: Mozilla/Add-ons/SDK/Tutorials/Adding_a_Button_to_the_Toolbar
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Adding_a_Button_to_the_Toolbar
+---
+<div class="note">
+<p>动手之前,必须先<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/安装">安装SDK</a>并学习<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_With_cfx"><code>cfx</code>基础</a>.</p>
+
+<p>这篇教程使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>API,需要Firefox 29或更新版本。</p>
+</div>
+
+<p>如果要给工具栏添加一个按钮,需要使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>或<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮</a>模块。</p>
+
+<p>新建一个目录,打开它,执行<code>cfx init</code>。</p>
+
+<p>然后,把这三个图标保存到data文件夹:</p>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="height: 16px; width: 16px;"></td>
+ <td>icon-16.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="height: 32px; width: 32px;"></td>
+ <td>icon-32.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="height: 64px; width: 64px;"></td>
+ <td>icon-64.png</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>随后打开lib目录下的main.js文件,添加如下代码:</p>
+
+<pre class="brush: js">var buttons = require('sdk/ui/button/action');
+var tabs = require("sdk/tabs");
+
+var button = buttons.ActionButton({
+  id: "mozilla-link",
+  label: "Visit Mozilla",
+  icon: {
+    "16": "./icon-16.png",
+    "32": "./icon-32.png",
+    "64": "./icon-64.png"
+  },
+  onClick: handleClick
+});
+
+function handleClick(state) {
+  tabs.open("https://www.mozilla.org/");
+}</pre>
+
+<p>现在输入<code>cfx run</code>来执行附加组件。按钮添加到了浏览器顶部的工具栏上:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/7641/mozilla-button.png" style="display: block; height: 221px; margin-left: auto; margin-right: auto; width: 382px;">你无法设置按钮的初始位置,但是用回可以使用浏览器的自定义功能移动它。其中的<code>id</code>属性是必需的,用来记录按钮的位置,因此,你最好不要在后续版本中修改它。</p>
+
+<p>单击按钮,<a href="https://www.mozilla.org/en-US/">https://www.mozilla.org/</a>将会在新的标签页中加载。</p>
+
+<h2 id="设定图标">设定图标</h2>
+
+<p>icon属性可以设定单个或是一组不同大小图标。如果你用的是一组不同大小的图标,浏览器将会自动选择最适合当前屏幕分辨率的,然后显示在浏览器界面的按钮上。<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#ActionButton(options)">更多内容,参考设定多个图标</a>。</p>
+
+<p>图标文件必须打包在附加组件内:它不可以指向一个远程文件。</p>
+
+<p>你只要正确地设置了按钮的<code>icon</code>属性,它就会立刻生效。你可以改变全局的,在特定窗口的或者是特定标签页中显示的图标或者是其他状态属性。<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action#Updating_state">更多内容,参考更新状态</a>。</p>
+
+<h2 id="附加一个面板">附加一个面板</h2>
+
+<p>如果你想把一个面板附加到按钮上,使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮</a>API。这就和动作按钮API类似,只不过多了一个boolean值属性,表示按钮是否被<code>checked</code>。附加面板,要把按钮传递给面板的<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/panel#show(options)"><code>show()</code></a>方法。<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle#Attaching_panels_to_buttons">更多细节,参考切换按钮文档</a>。</p>
+
+<h2 id="显示更多样的内容">显示更多样的内容</h2>
+
+<p>添加按钮做不到的复杂界面功能,需要使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_toolbar">工具栏</a>API。 使用工具栏API你可以得到一个用户界面内容的水平条。可以添加按钮或者是可以包含HTML,CSS,javaScript的<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_frame">frame</a>到工具栏上。</p>
+
+<h2 id="进一步学习">进一步学习</h2>
+
+<ul>
+ <li><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮参考</a></li>
+ <li><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮参考</a></li>
+ <li><a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_toolbar">工具栏参考</a></li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/implementing_the_widget/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/implementing_the_widget/index.html
new file mode 100644
index 0000000000..04e4a75d23
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/implementing_the_widget/index.html
@@ -0,0 +1,92 @@
+---
+title: 实现控件
+slug: Mozilla/Add-ons/SDK/Tutorials/Annotator/Implementing_the_widget
+tags:
+ - 附加组件
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Annotator/Implementing_the_widget
+---
+<p>我们想要控件做两件事:</p>
+
+<ul>
+ <li>点击鼠标左键,控件应当启用或禁用注释器。</li>
+ <li>点击鼠标右键,控件应当显示用户创建注释的清单。</li>
+</ul>
+
+<p>因为控件无法区分鼠标左右键的点击,我们应当使用内容脚本来捕获单击事件并发送相应的消息到附加组件。</p>
+
+<p>控件将有两个图标:一个在注释器启用时显示,一个在禁用时显示。</p>
+
+<p>因此,我们需要创建三个文件:控件的内容脚本和两个图标。</p>
+
+<p>在data子目录创建一个widget子目录,我们将把控件的文件保存在这里(注意,这个不是强制性的:你可以仅仅把它们放在data里,但分类放置会更加整洁)。</p>
+
+<h2 id="控件的内容脚本">控件的内容脚本</h2>
+
+<p>控件的内容脚本仅仅监听鼠标的左右单击并发送相应的消息到附加组件代码:</p>
+
+<pre class="brush: js">this.addEventListener('click', function(event) {
+ if(event.button == 0 &amp;&amp; event.shiftKey == false)
+ self.port.emit('left-click');
+
+ if(event.button == 2 || (event.button == 0 &amp;&amp; event.shiftKey == true))
+ self.port.emit('right-click');
+ event.preventDefault();
+}, true);</pre>
+
+<p>把它保存在data/widget并命名为widget.js。</p>
+
+<h2 id="控件图标">控件图标</h2>
+
+<p>你可以从这里复制图标:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6673/pencil-off.png"><img alt="" src="https://mdn.mozillademos.org/files/6675/pencil-on.png" style="width: 32px; height: 32px;"></p>
+
+<p>或者自己动手做你觉得有创造性的图标。把它们保存在data/widget目录。</p>
+
+<h2 id="main.js">main.js</h2>
+
+<p>现在在lib目录创建main.js并添加下列内容:</p>
+
+<pre class="brush: js">var widgets = require('sdk/widget');
+var data = require('sdk/self').data;
+
+var annotatorIsOn = false;
+
+function toggleActivation() {
+ annotatorIsOn = !annotatorIsOn;
+ return annotatorIsOn;
+}
+
+exports.main = function() {
+
+ var widget = widgets.Widget({
+ id: 'toggle-switch',
+ label: 'Annotator',
+ contentURL: data.url('widget/pencil-off.png'),
+ contentScriptWhen: 'ready',
+ contentScriptFile: data.url('widget/widget.js')
+ });
+
+ widget.port.on('left-click', function() {
+ console.log('activate/deactivate');
+ widget.contentURL = toggleActivation() ?
+ data.url('widget/pencil-on.png') :
+ data.url('widget/pencil-off.png');
+ });
+
+ widget.port.on('right-click', function() {
+ console.log('show annotation list');
+ });
+}</pre>
+
+<p>注释器默认禁用。它创建控件并通过切换注释器的活动状态来回应来自控件内容脚本的消息。注意,由于<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=626326">bug 626326</a>,附加组件状态栏的环境菜单会显示,尽管在控件的内容脚本中调用了event.preventDefault()。由于我们没有任何代码来显示注释,所以我们们仅仅记录右击事件到控制台。</p>
+
+<p>现在在注释器目录输入cfx run,你应该看见在附加组件状态栏的控件:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6679/widget-icon.png" style="width: 405px; height: 166px; display: block; margin-left: auto; margin-right: auto;"></p>
+
+<p>左击和右击应当产生合适的调试输出,同时左击应当改变控件的图标为启用状态。</p>
+
+<p> </p>
+
+<p>下一步,我们将添加代码来<a href="/en-US/Add-ons/SDK/Tutorials/Annotator/Creating_annotations">创建注释器</a>。</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/index.html
new file mode 100644
index 0000000000..4f76d67802
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/index.html
@@ -0,0 +1,36 @@
+---
+title: 注释器(Annotator)
+slug: Mozilla/Add-ons/SDK/Tutorials/Annotator
+tags:
+ - 附加组件
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Annotator
+---
+<div class="warning">
+<p>请注意教程中Widget API适合的浏览器版本。(译者注)</p>
+</div>
+
+<p>在这个教程中,我们将构建一个使用许多SDK高级API的附加组件.</p>
+
+<p>这个附加组件是一个注释器:它可以让用户选择网页的元素并输入有关的笔记(注释).注释器储存笔记.无论用户何时载入包含被注释元素的页面,这些元素都将会高亮显示,并且用户若把鼠标移动到被注释元素的上面,将会显示它的注释.</p>
+
+<p>接着我们将给出这个注释器设计的快速简介,然后一步步的讨论如何实现.</p>
+
+<p>如果你想参阅完整的附加组件,你可以在<a href="https://github.com/mozilla/addon-sdk/tree/master/examples/annotator">SDK例子目录</a>找到它.</p>
+
+<ul>
+ <li>
+ <p><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator/Overview">设计概述</a></p>
+ </li>
+ <li>
+ <p><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator/Implementing_the_widget">实现控件</a></p>
+ </li>
+ <li>
+ <p><a href="/en-US/Add-ons/SDK/Tutorials/Annotator/Creating_annotations">创建注释</a></p>
+ </li>
+ <li>
+ <p><a href="/en-US/Add-ons/SDK/Tutorials/Annotator/Storing_annotations">保存注释</a></p>
+ </li>
+ <li>
+ <p><a href="/en-US/Add-ons/SDK/Tutorials/Annotator/Displaying_annotations">显示注释</a></p>
+ </li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/overview/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/overview/index.html
new file mode 100644
index 0000000000..da94f8142a
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/annotator/overview/index.html
@@ -0,0 +1,54 @@
+---
+title: 概述
+slug: Mozilla/Add-ons/SDK/Tutorials/Annotator/Overview
+tags:
+ - addon sdk example
+ - annotator example
+ - 附加组件
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Annotator/Overview
+---
+<p>注释器使用内容脚本(content scripts)来构建用户界面,得到用户输入,并检查用户载入页面的DOM。</p>
+
+<p>同时,主要模块包括程序逻辑和调节不同SDK对象的交互。</p>
+
+<p>我们可以描述在主要模块和不同内容脚本的交互,像这样:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6671/annotator-design.png" style="display: block; margin-left: auto; margin-right: auto;"></p>
+
+<h2 id="用户界面">用户界面</h2>
+
+<p>注释器的主要用户界面由一个控件和三个面板组成。</p>
+
+<ul>
+ <li><a href="/en-US/Add-ons/SDK/High-Level_APIs/widget">控件(widget)</a>用来选择打开或关闭注释器,显示所有已经储存的注释列表。</li>
+ <li><strong>注释编辑器(annotation-editor)</strong><a href="/en-US/Add-ons/SDK/High-Level_APIs/panel">面板</a>用来让用户输入注释。</li>
+ <li><strong>注释列表(annotation-list)</strong>面板用来显示保存的注释清单。</li>
+ <li><strong>注释(annotation)</strong>面板显示单条注释。</li>
+</ul>
+
+<p>除此之外,我们使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/notifications">notifications</a> 模块来告知用户附加组件的储存限额已满。</p>
+
+<h2 id="用DOM工作">用DOM工作</h2>
+
+<p>我们将使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">page-mods</a> 来和用户打开的网页的DOM进行交互。</p>
+
+<ul>
+ <li>
+ <p><strong>选择器(selector)</strong>让用户选择一个元素来注释。它识别符合注释条件的页面元素,当鼠标在他们上方时高亮显示,并在用户点击高亮元素时通知主要的附加组件代码。</p>
+ </li>
+ <li>
+ <p><strong>匹配器(matcher)</strong>用来寻找被注释的元素:它初始化注释列表并网页中和注释相关连的元素。高亮网页上找到的关联元素,并高亮显示。当鼠标移动到已注释元素的上面,匹配器将通知显示注释面板的主要附加组件代码。</p>
+ </li>
+</ul>
+
+<h2 id="处理数据">处理数据</h2>
+
+<p>我们将使用<a href="/en-US/Add-ons/SDK/High-Level_APIs/simple-storage">simple-storage</a>模块来储存数据。</p>
+
+<p>由于我们将记录潜在的敏感信息,我们想阻止用户在隐私浏览模式下创建注释,最简单的方式是删除附加组件中“package.json“文件的<a href="/en-US/Add-ons/SDK/Tools/package_json#permissions">”private-browsing"键</a>。这样,附加组件就不能看见任何隐私浏览窗口,同时注释器的控件也将不再出现。</p>
+
+<h2 id="开始行动">开始行动</h2>
+
+<p>现在让我们来创建叫“注释器”的目录。Navigate to it and type <code>cfx init</code>.</p>
+
+<p>下一步,我们将<a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator/Implementing_the_widget">实现控件</a>。</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/display_a_popup/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/display_a_popup/index.html
new file mode 100644
index 0000000000..9bec4966d4
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/display_a_popup/index.html
@@ -0,0 +1,135 @@
+---
+title: 显示弹出对话框
+slug: Mozilla/Add-ons/SDK/Tutorials/Display_a_Popup
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Display_a_Popup
+---
+<div class="note">
+ <p>动手之前,必须先<a href="/en-US/Add-ons/SDK/Installation">安装SDK</a>并学习<a href="/en-US/Add-ons/SDK/Getting_Started_With_cfx"><code>cfx</code>基础知识</a>.</p>
+ <p>T这篇教程使用<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>API需要Firefox 29或更新版本。</p>
+</div>
+<p>可以使用<a href="/en-US/Add-ons/SDK/High-Level_APIs/panel"><code>面板(panel)</code></a>模块来显示弹出对话框。面板的内容通过HTML编写。你可以在面板上运行content script:尽管在面板里的脚本无法直接访问插件代码,但是你可以在面板脚本和插件代码间交换信息。</p>
+<p>这里,我们做了一个会在单击时显示面板的<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>。面板上有一个<code>&lt;textarea&gt;</code>元素:用户按下<code>return</code>键时,<code>&lt;textarea&gt;</code>的内容会被发送给插件代码主程序。插件代码主程序会<a href="/en-US/Add-ons/SDK/Tutorials/Logging">在控制台输出日志</a>。.</p>
+<p><img alt="" src="https://mdn.mozillademos.org/files/7647/panel.png" style="display: block; margin-left: auto; margin-right: auto;">The add-o插件由六个文件组成n consists of six files:</p>
+<ul>
+ <li><code>main.js</code>:插件主程序,在这里创建按钮和面板</li>
+ <li><code>get-text.js</code>:与面板内容交互的content脚本</li>
+ <li><code>text-entry.html</code>:面板的内容,由HTML编写</li>
+ <li><code>icon-16.png</code>,<code>icon-32.png</code>和<code>icon-64.png</code>:三种不同大小的图标</li>
+</ul>
+<p>"main.js"像这样:</p>
+<pre class="brush: js">var data = require("sdk/self").data;
+// 构造面板,从"data"目录的"text-entry.html"加载
+// 内容,然后加载"get-text.js"脚本。
+var text_entry = require("sdk/panel").Panel({
+  contentURL: data.url("text-entry.html"),
+  contentScriptFile: data.url("get-text.js")
+});
+
+// 创建按钮
+require("sdk/ui/button/action").ActionButton({
+  id: "show-panel",
+  label: "Show Panel",
+  icon: {
+    "16": "./icon-16.png",
+    "32": "./icon-32.png",
+    "64": "./icon-64.png"
+  },
+  onClick: handleClick
+});
+
+// 在用户点击按钮时显示面板。
+function handleClick(state) {
+  text_entry.show();
+}
+
+<code class="language-js"><span class="token comment">// When the panel is displayed it generated an event called
+</span><span class="token comment">// "show": we will listen for that event and when it happens,
+</span><span class="token comment">// send our own "show" event to the panel's script, so the
+</span><span class="token comment">// script can prepare the panel for display.</span></code>
+text_entry.on("show", function() {
+  text_entry.port.emit("show");
+});
+
+// 监听来自content脚本的text-entered消息。消息主体L是用户输入的文本。
+// 此实现,我们只在控制台显示日志。
+text_entry.port.on("text-entered", function (text) {
+  console.log(text);
+  text_entry.hide();
+});</pre>
+<p>content脚本"get-text.js"像这样:</p>
+<div>
+ <pre class="brush: js">// 用户按下回车,发送text-entered消息给main.js。
+// 消息主体是编辑框的内容。
+var textArea = document.getElementById("edit-box");
+textArea.addEventListener('keyup', function onkeyup(event) {
+ if (event.keyCode == 13) {
+ // Remove the newline.
+ text = textArea.value.replace(/(\r\n|\n|\r)/gm,"");
+ self.port.emit("text-entered", text);
+ textArea.value = '';
+ }
+}, false);
+// 监听由插件主程序发送的show事件。表示面板将要显示。
+//
+// 焦点放在textarea上,这样用户可以直接开始输入。
+self.port.on("show", function onShow() {
+ textArea.focus();
+});</pre>
+ <div>
+  </div>
+</div>
+<p>最后,"text-entry.html"文件定义了<code>&lt;textarea&gt;</code>元素:</p>
+<div>
+ <div>
+ <pre class="brush: html">&lt;html&gt;
+&lt;head&gt;
+    &lt;style type="text/css" media="all"&gt;
+      textarea {
+        margin: 10px;
+      }
+      body {
+        background-color: gray;
+      }
+    &lt;/style&gt;
+  &lt;/head&gt;
+&lt;body&gt;
+    &lt;textarea rows="13" cols="33" id="edit-box"&gt;&lt;/textarea&gt;
+  &lt;/body&gt;
+&lt;/html&gt;</pre>
+ <div>
+  </div>
+ </div>
+</div>
+<p>最后,把这三个图标文件保存在"data"目录:</p>
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="width: 16px; height: 16px;"></td>
+ <td>icon-16.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="width: 32px; height: 32px;"></td>
+ <td>icon-32.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="width: 64px; height: 64px;"></td>
+ <td>icon-64.png</td>
+ </tr>
+ </tbody>
+</table>
+<p>试用以下:保存在<code>lib</code>目录,其他五个文件存放在插件的<code>data</code>目录:</p>
+<pre>my-addon/
+ data/
+ get-text.js
+ icon-16.png
+ icon-32.png
+ icon-64.png
+ text-entry.html
+ lib/
+ main.js
+</pre>
+<p>运行插件,点击按钮,你就会看见一个面板。输入几行文本,然后按下回车,你就会看见控制台里的输出。</p>
+<p>自Firefox 30起,如果你使用<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮</a>,就可以<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle#Attaching_panels_to_buttons">给它附加一个面板</a>。</p>
+<h2 id="进一步学习">进一步学习</h2>
+<p>学习<code>panel</code>模块的更多内容,见<a href="/en-US/Add-ons/SDK/High-Level_APIs/panel"><code>panel</code> API参考</a>。</p>
+<p>学习关于按钮的更多内容,见<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>和<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_toggle">切换按钮</a>API参考。</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started/index.html
new file mode 100644
index 0000000000..225739de76
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started/index.html
@@ -0,0 +1,172 @@
+---
+title: 快速入门
+slug: Mozilla/Add-ons/SDK/Tutorials/Getting_started
+tags:
+ - add-on sdk开发
+ - cfx工具基础使用教程
+ - 火狐扩展程序
+translation_of: Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29
+---
+<p>{{AddonSidebar}}</p>
+
+<div class="note">
+<p>Add-on SDK 里包含了一个命令行工具,你可以用此工具来初始化、运行、测试以及打包 add on。 这个工具称为 jpm,基于 <a href="http://nodejs.org/">Node.js</a> 。它替代了以前的cfx工具。</p>
+
+<p>你可以在 Firefox 38或之后的版本中使用。</p>
+
+<p>本文阐述如何使用 jpm 开发。</p>
+</div>
+
+<p>本教程会过一遍使用 SDK 创建一个简单 add-on 的过程。</p>
+
+<h2 id="准备">准备</h2>
+
+<p>要使用 SDK 创建 add-on,你需要:</p>
+
+<ul>
+ <li>Firefox 38或以后版本。如果你需要在早期版本的 Firefox 上开发,你就要使用老的 cfx 工具。参看 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_started_(cfx)">cfx 快速入门</a>的说明。</li>
+ <li>命令行 jpm 工具。参看 <a href="/en-US/Add-ons/SDK/Tools/jpm#Installation">jpm 安装</a>的说明。一旦你已经完成这些工作,你就会在一个命令行提示符下。</li>
+</ul>
+
+<h2 id="初始化空的_add-on">初始化空的 add-on</h2>
+
+<p>在命令行提示符下,创建一个新目录。进入新文件夹,键入 <code>jpm init</code>,然后敲回车</p>
+
+<pre>mkdir my-addon
+cd my-addon
+jpm init
+</pre>
+
+<p>接着你会被要求提供一些关于你的 add-on 的信息:这会用来创建 <a href="/en-US/Add-ons/SDK/Tools/package_json">package.json</a> 文件。如果光按回车的话,就表示接受属性的默认值。关于 <code>jpm init</code> 的更多信息,参看 <a href="/en-US/Add-ons/SDK/Tools/jpm#Command_reference">jpm command reference</a>.</p>
+
+<p>一旦你设置了这些属性的值或者接受默认值,你会看到 "package.json" 的完整内容并被询问是否接受这些设置。</p>
+
+<h2 id="实现_add-on">实现 add-on</h2>
+
+<p>现在你可以写 add-on 的代码了。除非你修改了"entry point"的值(package.json 中的 "<a href="/en-US/Add-ons/SDK/Tools/package_json#main">main</a>"),一般情况将从你的 add-on 的根目录下的"index.js"文件开始。这个文件就是在之前步骤中创建的。打开这个文件并且添加以下代码:</p>
+
+<pre class="brush: js">var buttons = require('sdk/ui/button/action');
+var tabs = require("sdk/tabs");
+
+var button = buttons.ActionButton({
+ id: "mozilla-link",
+ label: "Visit Mozilla",
+ icon: {
+ "16": "./icon-16.png",
+ "32": "./icon-32.png",
+ "64": "./icon-64.png"
+ },
+ onClick: handleClick
+});
+
+function handleClick(state) {
+ tabs.open("http://www.mozilla.org/");
+}
+</pre>
+
+<div class="note">
+<p>注意在jpm中"entry point"的默认值为"index.js",意思是你的主文件是"index.js",且在你的 add-on的根目录下。</p>
+
+<p>cfx中,入口默认是"main.js",并且在"lib"目录下</p>
+</div>
+
+<p>保存文件</p>
+
+<p>接下来,在根目录下创建目录<strong>"data"</strong>。</p>
+
+<pre>mkdir data
+</pre>
+
+<p>并保存这三个图标文件到<strong>"data"</strong>目录:</p>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="height: 16px; width: 16px;"></td>
+ <td>icon-16.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="height: 32px; width: 32px;"></td>
+ <td>icon-32.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="height: 64px; width: 64px;"></td>
+ <td>icon-64.png</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>返回命令行,键入:</p>
+
+<pre>jpm run</pre>
+
+<p>这个 jpm 命令会运行一个带有你的 add-on 的 Firefox 的新实例。</p>
+
+<p>如果找不到 Firefox,你可能要为它提供一个路径(如在Ubuntu中):</p>
+
+
+<pre>jpm run -b /usr/bin/firefox</pre>
+
+<p>Firefox 启动以后,在浏览器右上角你能看到一个 Firefox logo 的图标。点击该图标,就会打开一个新标签页 <a href="http://www.mozilla.org/" rel="noreferrer">http://www.mozilla.org/</a>。</p>
+
+<p>这就是这个 add-on 的全部功能了。它用到了 SDK 的两个模块:<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> 模块,使你能加个按钮到浏览器上,以及 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs" rel="noreferrer">tabs</a> 模块,使你能完成对标签页的基本操作。本例中,我们以及创建了一个图标是Firefox图标的按钮,并添加一个点击处理程序,可以在新标签页中打开 Mozilla 页面。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/7643/mozilla-button.png" style="display: block; height: 221px; margin-left: auto; margin-right: auto; width: 382px;">试着编辑这个文件。例如,我们可以改变加载的页面:</p>
+
+<pre class="brush: js">var buttons = require('sdk/ui/button/action');
+var tabs = require("sdk/tabs");
+
+var button = buttons.ActionButton({
+ id: "mozilla-link",
+ label: "Visit Mozilla",
+ icon: {
+ "16": "./icon-16.png",
+ "32": "./icon-32.png",
+ "64": "./icon-64.png"
+ },
+ onClick: handleClick
+});
+
+function handleClick(state) {
+ tabs.open("https://developer.mozilla.org/");
+}</pre>
+
+<p>在命令行提示符下,再次执行 <code>jpm run</code>。这次点击按钮,它会带你到 <a href="https://developer.mozilla.org/">https://developer.mozilla.org/</a> 页面。</p>
+
+<h2 id="打包_add-on">打包 add-on</h2>
+
+<p>当你完成了 add-on 并准备发布它,你会需要把它打包为 XPI 文件。你能自己分发 XPI 文件,也可以把它们发布到 <a href="https://addons.mozilla.org" rel="noreferrer">https://addons.mozilla.org</a>,这样其他用户就能下载并按照它们。</p>
+
+<p>要构建 XPI,只要在 add-on 的根目录下运行命令 <code>jpm xpi</code>:</p>
+
+<pre>jpm xpi
+</pre>
+
+<p>你应该看到像这样的信息:</p>
+
+<pre>JPM info Successfully created xpi at /path/to/my-addon/@my-addon-0.0.1.xpi
+</pre>
+
+<p>要测试附加组件是否能正常运行,可以尝试在你自己的火狐中安装 XPI 文件。你可以在 Firefox 中按 Ctrl+O 组合键(Mac 中是 Cmd+O),或者选择"文件"菜单里的“打开”。这样会弹出一个文件选择对话框:转到"@my-addon.xpi"文件,打开并按照提示安装 add-on。</p>
+
+<p>注意 Firefox 默认需要 add-on 有签名,即使是本地开发的 add-on。安装完后他们会在已安装的 add-on 列表中出现,只因没有签名而被禁用。开发的时候,又或者你不准备发布,你可以打开 <a>about:config</a> 设置 <em>xpinstall.signatures.required</em> 为 <em>false</em> 来运行未经签名的组件。这个设置会应用到所有的 add-on,所以要十分小心,不要一不当心从别的地方安装了恶意组件。</p>
+
+<p>要发布你的 add-on,请<a href="https://addons.mozilla.org/en-US/developers/addon/submit/2">提交 XPI 文件到 addons.mozilla.org</a> 或者如果你想在你自己的服务器上发布,运行 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Tools/jpm#jpm_sign">jpm sign</a>。</p>
+
+<h2 id="总结">总结</h2>
+
+<p>本教程中我们使用了下面三个命令来构建和打包 add-on :</p>
+
+<ul>
+ <li><code>jpm init</code> 初始化一个空的 add-on 模板</li>
+ <li><code>jpm run</code> 运行一个装有 add-on 的新 Firefox 实例,所以我们可以试用它</li>
+ <li><code>jpm xpi</code> 打包 add-on 为 XPI 文件,用来发布</li>
+</ul>
+
+<p>这是你在开发SDK add-on会用到的三个主要命令。完全的<a href="/en-US/Add-ons/SDK/Tools/jpm" rel="noreferrer">参考文档</a>包含了所以你能使用的命令,以及这些命令的可选项。</p>
+
+<p>这次开发的add-on 的代码用到了两个 SDK 模块,<a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> 和 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs" rel="noreferrer">tabs</a>。这儿有参考文档,描述 SDK 中所有<a href="/en-US/Add-ons/SDK/High-Level_APIs" rel="noreferrer">高层次</a>和<a href="/en-US/Add-ons/SDK/Low-Level_APIs" rel="noreferrer">低层次</a>的 API。</p>
+
+<h2 id="下一步">下一步?</h2>
+
+<p>要了解你能用 SDK API 做些什么,试着继续阅读<a href="/en-US/Add-ons/SDK/Tutorials" rel="noreferrer">教程</a>。</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started_(jpm)/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started_(jpm)/index.html
new file mode 100644
index 0000000000..e09d6d4e55
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/getting_started_(jpm)/index.html
@@ -0,0 +1,162 @@
+---
+title: JPM 入门!
+slug: Mozilla/Add-ons/SDK/Tutorials/Getting_Started_(jpm)
+tags:
+ - JPM
+ - add-on
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Getting_Started_(jpm)
+---
+<div class="note">
+<p>该附加SDK包含一个用于初始化,运行,测试和打包加载项的命令行工具。当前工具称为jpm,并且基于  <a href="http://nodejs.org/">Node.js</a> .它替代了旧的cfx工具。</p>
+
+<p>Firefox 38 以上的版本才可以使用jpm。</p>
+
+<p>本文介绍如何使用jpm开发。</p>
+</div>
+
+<p>本教程将介绍使用SDK创建一个简单的附加组件。</p>
+
+<h2 id="先决条件">先决条件</h2>
+
+<p>要使用SDK为Firefox创建附加组件,您需要:</p>
+
+<ul>
+ <li>备好 Firefox 38 或更高版本浏览器,否则抱着你亲爱的cfx古董去死吧,出门左转 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_started">getting started with cfx</a> 不谢。</li>
+ <li>命令行 JPM 工具,至 <a href="/en-US/Add-ons/SDK/Tools/jpm#Installation">installing jpm</a> 此处领取。// 后面这句是废话不翻译</li>
+</ul>
+
+<h2 id="初始化一个空的附加组件">初始化一个空的附加组件</h2>
+
+<p>在命令提示符下,创建一个新目录。导航到它,键入 <code>jpm init, </code>然后按Enter键<code>:</code></p>
+
+<pre>mkdir my-addon
+cd my-addon
+jpm init
+</pre>
+
+<p>You'll then be asked to supply some information about your add-on: this will be used to create your add-on's <a href="/en-US/Add-ons/SDK/Tools/package_json">package.json</a> file. For now, just press Enter to accept the default for each property. For more information on <code>jpm init</code>, see the <a href="/en-US/Add-ons/SDK/Tools/jpm#Command_reference">jpm command reference</a>.</p>
+
+<p>Once you've supplied a value or accepted the default for these properties, you'll be shown the complete contents of "package.json" and asked to accept it.</p>
+
+<h2 id="实现附加组件">实现附加组件</h2>
+
+<p>Now you can write the add-on's code. Unless you've changed the value of "entry point" ("<a href="/en-US/Add-ons/SDK/Tools/package_json#main">main</a>" in package.json), this goes in "index.js" file in the root of your add-on. This file was created for you in the previous step. Open it and add the following code:</p>
+
+<pre class="brush: js">var buttons = require('sdk/ui/button/action');
+var tabs = require("sdk/tabs");
+
+var button = buttons.ActionButton({
+ id: "mozilla-link",
+ label: "Visit Mozilla",
+ icon: {
+ "16": "./icon-16.png",
+ "32": "./icon-32.png",
+ "64": "./icon-64.png"
+ },
+ onClick: handleClick
+});
+
+function handleClick(state) {
+ tabs.open("http://www.mozilla.org/");
+}
+</pre>
+
+<div class="note">
+<p>Note that "entry point" defaults to "index.js" in jpm, meaning that your main file is "index.js", and it is found directly in your add-on's root.</p>
+
+<p>In cfx, the entry point defaults to "main.js", and is located in the "lib" directory under the add-on's root.</p>
+</div>
+
+<p>Save the file.</p>
+
+<p>Next, create a directory called "data" in your add-on's root, and save these three icon files to the "data" directory:</p>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7635/icon-16.png" style="height: 16px; width: 16px;"></td>
+ <td>icon-16.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7637/icon-32.png" style="height: 32px; width: 32px;"></td>
+ <td>icon-32.png</td>
+ </tr>
+ <tr>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/7639/icon-64.png" style="height: 64px; width: 64px;"></td>
+ <td>icon-64.png</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>Back at the command prompt, type:</p>
+
+<pre>jpm run</pre>
+
+<p>This is the jpm command to run a new instance of Firefox with your add-on installed.</p>
+
+<p>If Firefox can not be located, you may need to provide the path to it (example in Ubuntu):</p>
+
+
+<pre>jpm run -b /usr/bin/firefox</pre>
+
+<p>When Firefox launches, in the top-right corner of the browser you'll see an icon with the Firefox logo. Click the icon, and a new tab will open with <a href="http://www.mozilla.org/" rel="noreferrer">http://www.mozilla.org/</a> loaded into it.</p>
+
+<p>That's all this add-on does. It uses two SDK modules: the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> module, which enables you to add buttons to the browser, and the <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs" rel="noreferrer">tabs</a> module, which enables you to perform basic operations with tabs. In this case, we've created a button whose icon is the Firefox icon, and added a click handler that loads the Mozilla home page in a new tab.</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/7643/mozilla-button.png" style="display: block; height: 221px; margin-left: auto; margin-right: auto; width: 382px;">Try editing this file. For example, we could change the page that gets loaded:</p>
+
+<pre class="brush: js">var buttons = require('sdk/ui/button/action');
+var tabs = require("sdk/tabs");
+
+var button = buttons.ActionButton({
+ id: "mozilla-link",
+ label: "Visit Mozilla",
+ icon: {
+ "16": "./icon-16.png",
+ "32": "./icon-32.png",
+ "64": "./icon-64.png"
+ },
+ onClick: handleClick
+});
+
+function handleClick(state) {
+ tabs.open("https://developer.mozilla.org/");
+}</pre>
+
+<p>At the command prompt, execute <code>jpm run</code> again. This time clicking it takes you to <a href="https://developer.mozilla.org/">https://developer.mozilla.org/</a>.</p>
+
+<h2 id="Packaging_the_add-on">Packaging the add-on</h2>
+
+<p>When you've finished the add-on and are ready to distribute it, you'll need to package it as an XPI file. This is the installable file format for Firefox add-ons. You can distribute XPI files yourself or publish them to <a href="https://addons.mozilla.org" rel="noreferrer">https://addons.mozilla.org</a> so other users can download and install them.</p>
+
+<p>To build an XPI, just execute the command <code>jpm xpi</code> from the add-on's directory:</p>
+
+<pre>jpm xpi
+</pre>
+
+<p>You should see a message like:</p>
+
+<pre>JPM info Successfully created xpi at /path/to/getting-started/@getting-started.xpi
+</pre>
+
+<p>To test that this worked, try installing the XPI file in your own Firefox installation. You can do this by pressing the Ctrl+O key combination (Cmd+O on Mac) from within Firefox, or selecting the "Open" item from Firefox's "File" menu. This will bring up a file selection dialog: navigate to the "@getting-started.xpi" file, open it and follow the prompts to install the add-on.</p>
+
+<h2 id="Summary">Summary</h2>
+
+<p>In this tutorial we've built and packaged an add-on using three commands:</p>
+
+<ul>
+ <li><code>jpm init</code> to initialize an empty add-on template</li>
+ <li><code>jpm run</code> to run a new instance of Firefox with the add-on installed, so we can try it out</li>
+ <li><code>jpm xpi</code> to package the add-on into an XPI file for distribution</li>
+</ul>
+
+<p>These are the three main commands you'll use when developing SDK add-ons. There's comprehensive <a href="/en-US/Add-ons/SDK/Tools/jpm" rel="noreferrer">reference documentation</a> covering all the commands you can use and all the options they take.</p>
+
+<p>The add-on code itself uses two SDK modules, <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> and <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs" rel="noreferrer">tabs</a>. There's reference documentation for all the <a href="/en-US/Add-ons/SDK/High-Level_APIs" rel="noreferrer">high-level</a> and <a href="/en-US/Add-ons/SDK/Low-Level_APIs" rel="noreferrer">low-level</a> APIs in the SDK.</p>
+
+<h2 id="What's_next">What's next?</h2>
+
+<p>To get a feel for some of the things you can do with the SDK APIs, try working through some of the <a href="/en-US/Add-ons/SDK/Tutorials" rel="noreferrer">tutorials</a>.</p>
+
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/index.html
new file mode 100644
index 0000000000..03173c3219
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/index.html
@@ -0,0 +1,144 @@
+---
+title: 教程
+slug: Mozilla/Add-ons/SDK/Tutorials
+tags:
+ - 插件SDK
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials
+---
+<p>{{LegacyAddonsNotice}}{{AddonSidebar}}</p>
+
+<p>本文列出了许多关于如何通过SDK完成特定任务要求的实际动手的文章。</p>
+
+<hr>
+<h3 id="开发之旅"><a name="getting-started">开发之旅</a></h3>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Installation">安装</a></dt>
+ <dd>在Windows, OS X和Linux上下载,安装,初始化SDK工具。</dd>
+</dl>
+
+<dl>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Troubleshooting">常见问题</a></dt>
+ <dd>解决常见问题的建议和获取更多帮助。</dd>
+</dl>
+</div>
+
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_started">快速开始</a></dt>
+ <dd>走马观花地使用SDK开发一个简单的扩展</dd>
+</dl>
+</div>
+</div>
+
+<hr>
+<h3 id="创建用户交互界面"><a name="create-user-interfaces">创建用户交互界面</a></h3>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Adding_a_Button_to_the_Toolbar">添加一个工具按钮</a></dt>
+ <dd>添加一个按钮到火狐Add-on工具栏。</dd>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Add_a_Menu_Item_to_Firefox">添加一个菜单选项到火狐</a></dt>
+ <dd>添加多个菜单选项到火狐主菜单。</dd>
+</dl>
+</div>
+
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Display_a_Popup">显示一个弹出对话框</a></dt>
+ <dd>通过HTML和JavaScript实现并显示一个弹窗对话框。</dd>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/添加一个菜单项">添加一个上下文菜单</a></dt>
+ <dd>添加一个上下文菜单(一般都是右键菜单)到火狐浏览器</dd>
+</dl>
+</div>
+</div>
+
+<hr>
+<h3 id="与浏览器交互"><a name="interact-with-the-browser">与浏览器交互</a></h3>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Open_a_Web_Page">打开Web页面</a></dt>
+ <dd>在一个新的浏览器选项卡里打开一个Web页面或窗口使用tabs模块并获取内容。</dd>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Listen_for_Page_Load">监听页面加载</a></dt>
+ <dd>当新页面载入时使用tabs模块得到通知并获取页面内容。</dd>
+</dl>
+</div>
+
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/List_Open_Tabs">获取打开的选项卡(Tab)列表</a></dt>
+ <dd>使用tabs模块遍历当前打开的tab,并获取其内容。</dd>
+</dl>
+</div>
+</div>
+
+<hr>
+<h3 id="更改网页"><a name="modify-web-pages">更改网页</a></h3>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Modifying_Web_Pages_Based_on_URL">更改网页通过URL</a></dt>
+ <dd>基于URL过滤网页:当载入的页面的URL与过滤器匹配时执行特定的脚本。</dd>
+</dl>
+</div>
+
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">修改页面内容</a></dt>
+ <dd>动态加载脚本到当前页面。</dd>
+</dl>
+</div>
+</div>
+
+<hr>
+<h3 id="开发技术"><a name="development-techniques">开发技术</a></h3>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/日志">日志</a></dt>
+ <dd>在终端中记录日志以便调试。</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Creating_reusable_modules">创建可复用的模块</a></dt>
+ <dd>拆分扩展程序为多个分离的模块,可以使开发调试和维护更加简单。封装你的模块使其成为可复用的包,以便其他开发者可以再次使用。</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Unit_testing">单元测试</a></dt>
+ <dd>使用SDK的测试框架书写和进行单元测试。</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Chrome_authority">Chrome授权 </a></dt>
+ <dd>获得Components对象,使你的扩展程序能够加载和使用任何XPCOM对象。</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Creating_event_targets">创建事件目标</a></dt>
+ <dd>使你定义的对象能够响应相关事件。</dd>
+</dl>
+</div>
+
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Listening_for_load_and_unload">监听载入和卸载</a></dt>
+ <dd>当你的扩展程序被加载和卸载时获得通知,并从终端传递参数给扩展程序。</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Add_a_Menu_Item_to_Firefox">使用第三方模块</a></dt>
+ <dd>安装和使用与SDK无关额外的模块</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/l10n">本地化</a></dt>
+ <dd>书写本地化代码.</dd>
+ <dt><a href="/zh-CN/Add-ons/SDK/Tutorials/Mobile_development">移动开发</a></dt>
+ <dd>为Andriod上的火狐浏览器开发扩展程序。</dd>
+ <dt><a href="/zh-CN/Add-ons/Add-on_Debugger">扩展调试</a></dt>
+ <dd>调试扩展应用的JavaScript。</dd>
+</dl>
+</div>
+</div>
+
+<hr>
+<h3 id="打包"><a name="putting-it-together">打包</a></h3>
+
+<div class="column-container">
+<div class="column-half">
+<dl>
+ <dt><a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Annotator">扩展应用:Annotator</a></dt>
+ <dd>一起开发一个相对复杂的扩展应用。</dd>
+</dl>
+</div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/installation/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/installation/index.html
new file mode 100644
index 0000000000..4313836979
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/installation/index.html
@@ -0,0 +1,135 @@
+---
+title: 安装
+slug: Mozilla/Add-ons/SDK/Tutorials/Installation
+tags:
+ - cfx安装
+ - 配置cfx环境
+translation_of: Mozilla/Add-ons/SDK/Tools/jpm#Installation
+---
+<h2 id="先决条件">先决条件</h2>
+
+<p><span style="color: #ff0000;">请不要把任何相关的开发工具和扩展程序(命名推荐小写英文和数字,不推荐特殊符号等),放到有空格的目录(如Progaram Files\Python),会导致意想不到的错误,无法进行后续操作。(最新开发SDK可能修复了该错误,参见https://github.com/mozilla/addon-sdk/pull/1738)</span></p>
+
+<p>开发 Add-on SDK,你需要:</p>
+
+<ul>
+ <li>
+ <p><a href="http://www.python.org/">Python</a> 2.5,2.6 或 2.7。 <span class="short_text" id="result_box" lang="zh-CN"><span>需要注意的是在任何平台<span class="short_text" id="result_box" lang="zh-CN"><span>都是不支持</span></span></span></span> <span class="short_text" id="result_box" lang="zh-CN"><span>Python</span><span>3.x版本的</span></span> 。确保你已经安装过Python。</p>
+ </li>
+ <li>
+ <p>Firefox火狐浏览器(本教程针对最新的浏览器)。</p>
+ </li>
+ <li>
+ <p><span class="short_text" id="result_box" lang="zh-CN"><span>SDK本身</span><span>:</span><span>可以获取</span><span>SDK的最新</span><span>稳定版本</span><span>为</span></span> <a href="https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/jetpack-sdk-latest.tar.gz">tarball压缩包</a> 或 <a href="https://ftp.mozilla.org/pub/mozilla.org/labs/jetpack/jetpack-sdk-latest.zip">zip 文件</a>。</p>
+ </li>
+</ul>
+
+<p>另外,<span class="short_text" id="result_box" lang="zh-CN"><span>你</span><span>可以从它</span><span>的<a href="https://github.com/mozilla/addon-sdk">GitHub repository</a></span><span>库中</span><span>得到最新的</span><span>开发版本</span></span>。</p>
+
+<h2 id="为AMO开发扩展">为AMO开发扩展</h2>
+
+<p>如果提交到AMO只有最新发布或许使用。</p>
+
+<p class="ordinary-output target-output"><span>git</span><span> archive </span><span>需要扩展</span><span>一些Git</span><span>属性</span><span>占位符</span><span>。</span></p>
+
+<pre class="language-html">git checkout 1.16
+
+git archive 1.16 python-lib/cuddlefish/_version.py | tar -xvf -</pre>
+
+<h2 id="通过Homebrew自动安装到Mac_OS_X">通过Homebrew自动安装到Mac OS X</h2>
+
+<p><span class="short_text" id="result_box" lang="zh-CN"><span>使用以下命令</span><span>通过</span></span> <a href="http://brew.sh/">homebrew</a><span class="short_text" id="result_box" lang="zh-CN"><span>来安装</span><span>SDK<span class="short_text" id="result_box" lang="zh-CN"><span><span class="short_text" id="result_box" lang="zh-CN"><span>插件</span></span></span></span>工具:</span></span></p>
+
+<pre>brew install mozilla-addon-sdk</pre>
+
+<h2 id="安装到Mac_OS_XLinux">安装到Mac OS X/Linux</h2>
+
+<p><span class="short_text" id="result_box" lang="zh-CN"><span><span class="short_text" id="result_box" lang="zh-CN"><span>无论你</span><span>选择哪个方式都要</span></span>解压缩</span><span>文件的内容</span><span>作为根路径,</span><span>并通过</span><span>shell</span><span>/</span><span>命令提示符切换到</span><span>SDK的</span><span>根目录下</span><span>。</span><span>例如:</span></span></p>
+
+<pre>tar -xf addon-sdk.tar.gz
+cd addon-sdk
+</pre>
+
+<p>如果你是<span class="short_text" id="result_box" lang="zh-CN"><span>Bash的</span><span>用户,则继续运行</span></span>(大多数人都是的):</p>
+
+<pre>source bin/activate
+</pre>
+
+<p><span class="short_text" id="result_box" lang="zh-CN"><span>如果你是</span><span>一个非</span><span>Bash的</span><span>用户</span><span>,</span><span>你应该运行</span><span>:</span></span></p>
+
+<pre>bash bin/activate
+</pre>
+
+<p><span class="short_text" id="result_box" lang="zh-CN"><span>命令提示符</span><span>现在应该</span><span>有一个包含</span><span>SDK的</span><span>根</span><span>目录名称</span><span>的新的前缀</span><span>:</span></span></p>
+
+<pre>(addon-sdk)~/mozilla/addon-sdk &gt;
+</pre>
+
+<h2 id="安装到Windows">安装到Windows</h2>
+
+<p>同样解压缩文件,并通过命令符进入到SDK根目录下,例如:</p>
+
+<pre>7z.exe x addon-sdk.zip
+cd addon-sdk
+</pre>
+
+<p>接着运行激活命令:</p>
+
+<pre>bin\activate
+</pre>
+
+<p><span class="short_text" id="result_box" lang="zh-CN"><span>同样可以看到命令提示符</span><span>现在应该</span><span>有一个包含</span><span>SDK的</span><span>根</span><span>目录名称</span><span>的<span class="short_text" id="result_box" lang="zh-CN"><span>新的</span></span>前缀</span><span>:</span></span></p>
+
+<pre>(C:\Users\mozilla\sdk\addon-sdk) C:\Users\Work\sdk\addon-sdk&gt;
+</pre>
+
+<h2 id="SDK_的虚拟环境">SDK 的虚拟环境</h2>
+
+<p><span id="result_box" lang="zh-CN"><span><span id="result_box" lang="zh-CN"><span>当命令</span><span>提示符</span></span>出现新的</span><span>前缀</span><span>表明</span><span>你的</span><span>已经搭建好了SDK的</span><span>运行环境</span><span>,那么你就可以使用</span><span>Add</span><span class="atn">-</span><span>on SDK来开发</span><span>的</span><span>命令行工具</span><span>。</span></span></p>
+
+<p>任何时候,你都可以通过运行 <code>deactivate 命令停用虚拟环境</code>.</p>
+
+<p class="ordinary-output target-output"><span>配置好的虚拟环境是特定于这个特定的命令提示符。</span><span>如果您关闭命令提示符, 它会关闭运行环境,你需要<code>source bin/activate</code>或<code> bin\activate 在</code>一个新的命令提示符重新激活它。</span><span>如果你</span><span>打开一个新命令提示符</span><span>,</span><span id="result_box" lang="zh-CN"><span>SDK将</span><span>不会被激活</span><span>在新的提示</span></span><span>。</span></p>
+
+<p><span id="result_box" lang="zh-CN"><span>可以</span><span>将SDK</span><span>的多个副本</span><span>拷贝在</span><span>磁盘上的</span><span>不同位置</span><span>,并</span><span>在它们之间切换</span><span>,甚至可以</span><span>让他们<span id="result_box" lang="zh-CN"><span>同时</span><span>激活</span></span>运行在</span><span>不同的命令</span><span>提示</span><span>符</span><span>。</span></span></p>
+
+<h3 id="制作启动项">制作启动项</h3>
+
+<p><span id="result_box" lang="zh-CN"><span>所有 </span><code>activate </code><span>的作用是通过设置环境变量,<span id="result_box" lang="zh-CN"><span>使位于</span><span>顶层</span><code> bin </code><span>目录下</span><span>的脚本</span></span></span><span> </span><span>位于当前命令符下</span><span>,制作的启动项 ,</span><span>通过永久</span><span>环境中的这些</span><span>变量</span><span>设置,以便</span><span>每一个新的</span><span>命令提示符下</span><span>都能读取它们</span><span>。</span><span>那么</span><span>就不需要每次都去打开新的命令提示符来激活</span><span><code> activate </code>。</span></span></p>
+
+<p class="ordinary-output target-output"><span>因为变量精确设置可能随SDK发布新版本的变化,所以最好是指激活脚本来确定哪些变量需要设置。</span><span>激活</span><span>使用不同的</span><span>脚本</span><span>设置</span><span>bash</span><span>环境</span><span>不同的变量</span><span>(</span><span>Linux</span><span>和</span><span>MAC</span><span> OS X</span><span>和Windows</span><span>环境</span><span>)</span><span>。</span></p>
+
+<h4 id="Windows">Windows</h4>
+
+<p><span id="result_box" lang="zh-CN"><span>在Windows上,</span><span>使用</span><span> <code>bin\activate\</code><code>activate.bat</code></span><span>批处理脚本,也可以</span><span>使用命令行</span><code>setx</code><span>工具或</span><span>控制面板</span><span>激活</span><span>永久</span><span>使用</span><span>。</span></span></p>
+
+<h4 id="LinuxMac_OS_X">Linux/Mac OS X</h4>
+
+<p>在 Linux 和 Mac OS X,<span id="result_box" lang="zh-CN"><span>使用</span></span><code>source bin/activate</code>/<code>activate</code> bash 脚本, 你可以 <code>~/.bashrc</code> ( Linux) <code>或~/.bashprofile</code> (Mac OS X) 来激活。</p>
+
+<p><span class="short_text" id="result_box" lang="zh-CN"><span>作为替代</span><span>,你</span><span>可以在</span><code> ~/bin </code><span class="hps">目录中</span><span>创建到</span><span>cfx </span><span>程序</span><span>的符号链接</span><span>:</span></span></p>
+
+<pre>ln -s PATH_TO_SDK/bin/cfx ~/bin/cfx
+</pre>
+
+<h2 id="完整性检查"><span class="short_text" id="result_box" lang="zh-CN"><span>完整性检查</span></span></h2>
+
+<p><span class="short_text" id="result_box" lang="zh-CN"><span>在shell提示符</span></span>运行:</p>
+
+<pre>cfx
+</pre>
+
+<p>它会产生下面信息,这里是第一行内容,后面<span>是</span><span>大量的</span><span>使用信息</span><span>:</span></p>
+
+<pre>Usage: cfx [options] [command]
+</pre>
+
+<p><span id="result_box" lang="zh-CN"><span>这是</span></span> <a href="/en-US/Add-ons/SDK/Tools/cfx"><span id="result_box" lang="zh-CN"><span>CFX</span><span>命令行程序</span></span></a>, <span id="result_box" lang="zh-CN"><span>是</span><span>主</span><span>界面</span><span>加载项</span><span>的SDK</span></span>,<span id="result_box" lang="zh-CN"><span>可以使用</span><span>它来</span><span>启动Firefox</span><span>和测试</span><span>插件,</span><span>打包</span><span>附加</span><span>分发</span><span>,查看</span><span>​​文档和</span><span>运行单元测试</span><span>。</span></span></p>
+
+<h2 id="出现问题">出现问题?</h2>
+
+<p>尝试通过<a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Troubleshooting">故障排除页面</a>来解决遇到的问题。</p>
+
+<h2 id="下一步">下一步</h2>
+
+<p>接下来, 开始学习 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_Started_With_cfx">cfx</a> 教程, <span class="short_text" id="result_box" lang="zh-CN"><span>其中</span><span>介绍了如何</span><span>使用</span><span>CFX的</span><span>工具来创建</span><span>附加组件</span><span>。</span></span></p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/l10n/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/l10n/index.html
new file mode 100644
index 0000000000..5083be5b5c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/l10n/index.html
@@ -0,0 +1,381 @@
+---
+title: Localization
+slug: Mozilla/Add-ons/SDK/Tutorials/l10n
+tags:
+ - Add-on SDK
+ - 本地化
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/l10n
+---
+<p>该SDK支持本地化字符串出现在:</p>
+
+<ul>
+ <li><a href="/en-US/Add-ons/SDK/Tutorials/l10n#Using_Localized_Strings_in_JavaScript">你的主附加组件Add-on的 JavaScript代码</a></li>
+ <li><a href="/en-US/Add-ons/SDK/Tutorials/l10n#Using_Localized_Strings_in_HTML">你的附加组件一起打包的HTML文件</a></li>
+ <li><a href="/en-US/Add-ons/SDK/Tutorials/l10n#Using_Localized_Strings_in_Preferences">你的附加组件首选项中的 title 标题和 description 描述域</a></li>
+</ul>
+
+<p>目前为止还不支持本地化CSS和content scripts。</p>
+
+<h2 id="本地化字符串">本地化字符串</h2>
+
+<p>翻译后的字符串都保存在你的add-on扩展目录下一个名为 "locale"的目录 ,每个本地化地域对应一个文件。这些文件:</p>
+
+<ul>
+ <li>使用文件<a href="http://en.wikipedia.org/wiki/.properties"><code>.properties</code> 格式</a></li>
+ <li>被命名为 "xx-YY.properties", 这里的 "xx-YY" 是 <a href="https://wiki.mozilla.org/L10n:Locale_Codes"> </a> <a href="https://wiki.mozilla.org/L10n:Locale_Codes">name of the locale(本地化区域的名称)</a></li>
+ <li>包含所有你想要本地化的字符串,其中由一个本地化字符串标识ID和对应的本地化翻译字符串以 <code>"标识ID=本地化翻译的字符串</code>" 的格式组成。(contain one entry for each string you want to localize, consisting of an identifier for the string and its translation in that locale, in the format <code>identifier=translation</code>.)</li>
+ <li>需要使用没有BOM的UTF-8格式来编码(need to use UTF-8 without BOM encoding)</li>
+</ul>
+
+<p>假设你的附加组件包含一个单一的本地化字符串,用英语表示为“Hello!”,你想提供英语和法语的本地化支持。</p>
+
+<p>你需要添加两个文件到"locale"目录:</p>
+
+<pre>my-addon/
+ data
+ lib
+ locale/
+ en-US.properties
+ fr-FR.properties
+</pre>
+
+<p>"en-US.properties" 文件中内容:</p>
+
+<pre>hello_id= Hello!
+</pre>
+
+<p>"fr-FR.properties" 文件中内容:</p>
+
+<pre>hello_id= Bonjour !
+</pre>
+
+<p>现在,每当你的JavaScript或HTML向本地化系统请求hello_id标识的翻译,它将获得与当前区域语言一致的翻译。</p>
+
+<h2 id="在HTML中使用本地化字符串">在HTML中使用本地化字符串</h2>
+
+<div class="note">
+<p>本例使用的 <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> API需要 Firefox 29 或者更高版本。</p>
+</div>
+
+<p>要从HTML中引用本地化字符串,需要添加一个 <code>data-l10n-id</code> 的属性,到你想本地化的字符串所属的HTML标签中,然后为该属性指定一个ID值(To reference localized strings from HTML, add a <code>data-l10n-id</code> attribute to the HTML tag where you want the localized string to appear, and assign the identifier to it):</p>
+
+<pre class="brush: html">&lt;html&gt;
+  &lt;body&gt;
+    &lt;h1 data-l10n-id="hello_id"&gt;&lt;/h1&gt;
+  &lt;/body&gt;
+&lt;/html&gt;
+</pre>
+
+<p>然后你就可以使用这个HTML文件来建立你的界面, 比如插入一个 panel 面板:</p>
+
+<pre class="brush: js">var button = require("sdk/ui/button/action").ActionButton({
+  id: "localized-hello",
+  label: "Localized hello",
+  icon: "./icon-16.png",
+  onClick: function() {
+    hello.show();
+  }
+});
+
+var hello = require("sdk/panel").Panel({
+  height: 75,
+  width: 150,
+  contentURL: require("sdk/self").data.url("my-panel.html")
+});</pre>
+
+<p>“en-US”和“fr-FR”提供了翻译标识为hello_id字符串的本地化文件,面板将根据当前区域语言设置,显示“Hello!”或者“Bonjour!”:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/7663/bonjour.png" style="width: 255px; height: 160px;"><img alt="" src="https://mdn.mozillademos.org/files/7665/hello.png" style="width: 255px; height: 160px;"></p>
+
+<p>翻译文本会插入到具有data-l10n-id属性集的节点中。任何之前存在的内容只是被替换掉了。(The translation is inserted into the node which has the <code>data-l10n-id</code> attribute set. Any previously existing content is just replaced.)</p>
+
+<p>本地化字符串只能作为text文本插入, 所以你不能使用下面的语句插入HTML:</p>
+
+<pre>hello_id= &lt;blink&gt;Hello!&lt;/blink&gt;
+</pre>
+
+<h3 id="Localizing_Element_Attributes">Localizing Element Attributes</h3>
+
+<div class="geckoVersionNote">这是 Firefox 39 上的新功能</div>
+
+<p><br>
+ 你可以在properties文件中,通过设置 l10n-id.attributeName 的值,本地化某些具有 l10n-id属性的元素的属性值。像这样(You can localize certain attributes of elements with an l10n-id by setting its value with l10n-id.attributeName in the properties file like):<br>
+  </p>
+
+<pre>hello_id.accesskey= H</pre>
+
+<p>可以支持以下几个属性:</p>
+
+<ul>
+ <li><strong>accesskey</strong></li>
+ <li><strong>alt</strong></li>
+ <li><strong>label</strong></li>
+ <li><strong>title</strong></li>
+ <li><strong>placeholder</strong></li>
+</ul>
+
+<p>更多的<a href="/en-US/docs/Web/Accessibility/ARIA"> ARIA</a> 属性<strong>aria-label</strong>, <strong>aria-valuetext</strong> 和 <strong>aria-moz-hint</strong> 的本地化将通过在Firefox OS上同样的别名被支持(Further the localization of the <a href="/en-US/docs/Web/Accessibility/ARIA">ARIA</a> attributes <strong>aria-label</strong>, <strong>aria-valuetext</strong> and <strong>aria-moz-hint</strong> are supported with the same aliases as on Firefox OS):</p>
+
+<ul>
+ <li><strong>ariaLabel</strong></li>
+ <li><strong>ariaValueText</strong></li>
+ <li><strong>ariaMozHint</strong></li>
+</ul>
+
+<h2 id="在JavaScript代码中使用本地化字符串">在JavaScript代码中使用本地化字符串</h2>
+
+<p>为了在主附加组件代码中引用本地化字符串,你需要这样做:</p>
+
+<pre class="brush: js">var _ = require("sdk/l10n").get;
+console.log(_("hello_id!"));</pre>
+
+<p><span>指定的 "_" 并不是必需的,但是作为<a href="https://www.gnu.org/software/gettext/gettext.html"> gettext </a>工具的默认约定,这能更好的配合其他默认使用 "_" 来表示本地化字符串的现有工具。</span></p>
+
+<ol>
+ <li>导入 <code>l10n</code> 模块,然后指定 "_" (下划线)为模块的 <code>get</code> 函数。</li>
+ <li>把所有涉及本地化的字符串放到 <code>_()</code> 函数中包括起来。</li>
+</ol>
+
+<p>如果你运行它,你会看到输出为预期的当前设置的区域语言:</p>
+
+<pre>info: Hello!
+</pre>
+
+<pre>info: Bonjour !
+</pre>
+
+<p>注意你不能在content scripts中 <code>require()</code> 一个模块,所以目前还不能在content script 中引用本地化字符串。</p>
+
+<h3 id="复数">复数</h3>
+
+<p> <code>l10n</code> 模快支持复数形式,不同的语言有不同的复数形态。例如,英语有两种形式:相对于"one"的单数形式,和对于"everything else, including zero"的复数形式:</p>
+
+<pre>one tomato
+no tomatoes
+two tomatoes
+</pre>
+
+<p>但是俄罗斯语对于以 1 结尾(除了11)的数字、以 2-4 结尾(除了12-14)的数字和其他数字,有着不同的复数形态:</p>
+
+<pre>один помидор // one tomato
+два помидора // two tomatoes
+пять помидоров // five tomatoes
+</pre>
+
+<p>SDK使用 <a href="http://cldr.unicode.org/index">Unicode CLDR</a> 数据描述由不同的语言使用的不同复数形式。</p>
+
+<h4 id="Unicode_CLDR_复数形式">Unicode CLDR 复数形式</h4>
+
+<p>Unicode CLDR项目定义了用于描述一个特定语言的多个规则的一种方案。在这个方案中一种语言对应最多有六种不同的范围的数字,有以下类别区分:<em>zero(零个),one(一个),two(两个),few(几个),many(很多),</em>和<em>other(其他)</em>。(The Unicode CLDR project defines a scheme for describing a particular language's plural rules. In this scheme a language maps each distinct range of numbers on to one of up to six forms, identified by the following categories: <em>zero</em>, <em>one</em>, <em>two</em>, <em>few</em>, <em>many</em>, and <em>other</em>.)</p>
+
+<p>英语有两种复数形式,可以表示为 "1" 映射到 "one" 和 "everything else" 映射到 "other"的形式(English has two forms, which can be described by mapping "1" to "one" and "everything else" to "other"):</p>
+
+<pre>one → n is 1;
+other → everything else
+</pre>
+
+<p>俄罗斯语有四种形式,可以使用以下方式表示:</p>
+
+<pre>one → n mod 10 is 1 and n mod 100 is not 11;
+few → n mod 10 in 2..4 and n mod 100 not in 12..14;
+many → n mod 10 is 0 or n mod 10 in 5..9 or n mod 100 in 11..14;
+other → everything else
+</pre>
+
+<p>所有语言的多个规则可以在CLDR的 <a href="http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html">语言复数规则</a> 页面查到 (即使这个规则表相对于 <a href="http://unicode.org/repos/cldr/trunk/common/supplemental/plurals.xml">CLDR XML source</a> 已经过时了).</p>
+
+<h4 id="SDK中的复数形式">SDK中的复数形式</h4>
+
+<p>代码中,在 <code>_()</code>函数中的本地化ID参数之后提供一个额外的参数,用来表示代表多少个项的本地化字符串(In the code, you supply an extra parameter alongside the identifier, describing how many items there are):</p>
+
+<pre class="brush: js">var _ = require("sdk/l10n").get;
+console.log(_("tomato_id"));
+console.log(_("tomato_id", 1));
+console.log(_("tomato_id", 2));
+console.log(_("tomato_id", 5));
+console.log(_("tomato_id", .5));</pre>
+
+<p>在 <code>.properties</code> 文件中通过使用 CLDR 关键字,对于每种语言可能的复数形式你可以自定义不同的本地化字符串。所以对于英语可以有两种本地化(注意"other" 分类不是 CDLR 关键字)。(In the <code>.properties</code> file for each language you can define a different localization for each plural form possible in that language, using the CLDR keywords. So in English we could have two plural localizations (note that the "other" category does <strong>not</strong> take the CLDR keyword))</p>
+
+<pre># en-US translations
+tomato_id[one]= %d tomato
+tomato_id= %d tomatoes
+</pre>
+
+<p>俄罗斯语中可以定义四种本地化的复数形式:</p>
+
+<pre># ru-RU translations
+tomato_id[one]= %d помидор
+tomato_id[few]= %d помидора
+tomato_id[many]= %d помидоров
+tomato_id= %d помидоры
+</pre>
+
+<p>The localization module itself understands the CLDR definitions for each language, enabling it to map between, for example, "2" in the code and "few" in the <code>ru-RU.properties</code> file. Then it retrieves and returns the localization appropriate for the count you supplied.</p>
+
+<h3 id="Placeholders">Placeholders</h3>
+
+<p>The <code>l10n</code> module supports placeholders, allowing you to insert a string which should not be localized into one which is. The following "en-US" and "fr-FR" ".properties" files include placeholders:</p>
+
+<pre># en-US translations
+hello_id= Hello %s!
+</pre>
+
+<pre># fr-FR translations
+hello_id= Bonjour %s !
+</pre>
+
+<p>To use placeholders, supply the placeholder string after the identifier:</p>
+
+<pre class="brush: js">var _ = require("sdk/l10n").get;
+console.log(_("hello_id", "Bob"));
+console.log(_("hello_id", "Alice"));</pre>
+
+<p>In the "en-US" locale, this gives us:</p>
+
+<pre>info: Hello Bob!
+info: Hello Alice!
+</pre>
+
+<p>In "fr-FR" we get:</p>
+
+<pre>info: Bonjour Bob !
+info: Bonjour Alice !
+</pre>
+
+<h3 id="Ordering_Placeholders">Ordering Placeholders</h3>
+
+<p>When a localizable string can take two or more placeholders, translators can define the order in which placeholders are inserted, without affecting the code.</p>
+
+<p>Primarily, this is important because different languages have different rules for word order. Even within the same language, though, translators should have the freedom to define word order.</p>
+
+<p>For example, suppose we want to include a localized string naming a person's home town. There are two placeholders: the name of the person and the name of the home town:</p>
+
+<pre class="brush: js">var _ = require("sdk/l10n").get;
+console.log(_("home_town_id", "Bob", "London"));</pre>
+
+<p>An English translator might want to choose between the following:</p>
+
+<pre>"&lt;town_name&gt; is &lt;person_name&gt;'s home town."
+</pre>
+
+<pre>"&lt;person_name&gt;'s home town is &lt;town_name&gt;"
+</pre>
+
+<p>To choose the first option, the <code>.properties</code> file can order the placeholders as follows:</p>
+
+<pre>home_town_id= %2s is %1s's home town.
+</pre>
+
+<p>This gives us the following output:</p>
+
+<pre>info: London is Bob's home town.
+</pre>
+
+<h2 id="在首选项设置中的本地化字符串">在首选项设置中的本地化字符串</h2>
+
+<p>通过加入一个 <a href="/en-US/Add-ons/SDK/High-Level_APIs/simple-prefs">"preferences" 字段的结构到你的附加组件的 "package.json" 文件</a>中,你可以为你的附加组件定义首选项选项,用户可以在Firefox的 <a href="https://support.mozilla.org/en-US/kb/Using%20extensions%20with%20Firefox#w_how-to-change-extension-settings">Add-ons Manager</a> 看到和编辑它。</p>
+
+<p>Preferences (首选项)有一个必需的title标题项和一个可选的description描述项 这些字符串将出现在 Add-ons Manager中,来帮助向用户解释各个首选项设置的意义。</p>
+
+<ul>
+ <li>
+ <p>要对preferences中的title标题部分进行本地化,所有在"properties"文件中,形式为preferences中的name后面接着 <code>_title</code> 的本地化标识ID,其对应的值就是标题的本地化字符串。(To provide the localized form of the preference title, include an entry in your "properties" file whose identifier is the preference name followed by <code>_title</code>, and whose value is the localized title.)</p>
+ </li>
+ <li>
+ <p>要对preferences中的description描述部分进行本地化,所有在"properties"文件中,形式为preferences中的name后面接着 <code>_description</code> 的本地化标识ID,其对应的值就是描述的本地化字符串。(To provide the localized form of the preference description, include an entry in your "properties" file whose identifier is the preference name followed by <code>_description</code>, and whose value is the localized description.)</p>
+ </li>
+</ul>
+
+<p>例如, 假设你的 "package.json" 中只定义了一个设置选项:</p>
+
+<pre>{
+ "preferences": [
+ {
+ "type": "string",
+ "name": "monster_name",
+ "value": "Gerald",
+ "title": "Name"
+ }
+ ],
+ "name": "monster-builder",
+ "license": "MPL 2.0",
+ "author": "me",
+ "version": "0.1",
+ "fullName": "Monster Builder",
+ "id": "monster-builder@me.org",
+ "description": "Build your own monster"
+}
+</pre>
+
+<p>在你的"en-US.properties"文件中, 应该包括下面两个项:</p>
+
+<pre>monster_name_title= Name
+monster_name_description= What is the monster's name?
+</pre>
+
+<p>在你的"fr-FR.properties"文件中, 应该包括下面两个法语的翻译项:</p>
+
+<pre>monster_name_title= Nom
+monster_name_description= Quel est le nom du monstre ?
+</pre>
+
+<p>现在,当浏览器的区域设置为 "en-US", 用户会在 Add-ons Manager看到这样:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6525/preference-us.png" style="width: 571px; height: 77px;"></p>
+
+<p>当浏览器区域设置为 "fr-FR", 用户会看到:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6523/preference-french.png"></p>
+
+<p>下拉菜单<code>menulist</code>和单选按钮<code>radio</code>的类型有多个选项,每一个选项的标签属性都会展示给用户。如果本地化文件中有一项是以前缀是"{name} _options" 为键的键值对,其中"{name}"是选项的标签名字,该键值对的值就是一个选项标签的本地化字符串。(The <code>menulist</code> and the <code>radio</code> preference types have options. The <code>label</code> attribute of each option is displayed to the user. If the locale file has a entry with the value of the <code>label</code> attribute prefixed with "{name}_options." as its key, where {name} is the name of the preference, its value is used as a localized label.)</p>
+
+<h2 id="Using_Identifiers">Using Identifiers</h2>
+
+<p>If the localization system can't find an entry for a particular identifier using the current locale, then it just returns the identifier itself.</p>
+
+<p>This has the nice property that you can write localizable, fully functional add-ons without having to write any locale files. You can just use the default language strings as your identifier, and subsequently supply <code>.properties</code> files for all the additional locales you want to support.</p>
+
+<p>For example, in the case above you could use "Hello!" as the identifier, and just have one <code>.properties</code> file for the "fr-FR" locale:</p>
+
+<pre>Hello!= Bonjour !
+</pre>
+
+<p>Then when the locale is "en-US", the system would fail to find a <code>.properties</code> file, and return "Hello!".</p>
+
+<p>However, this approach makes it difficult to maintain an add-on which has many localizations, because you're using the default language strings both as user interface strings and as keys to look up your translations. This means that if you want to change the wording of a string in the default language, or fix a typo, then you break all your locale files.</p>
+
+<h2 id="Locale_Updater">Locale Updater</h2>
+
+<p>The <a href="https://github.com/downloads/ochameau/locale-updater/locale-updater.xpi">locale updater</a> add-on makes it easier to update locale files. Once you've installed it, open the Add-on Manager, and you'll see a see a new button labeled "Update l10n" next to each add-on you've installed:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6515/locale-updater.png"></p>
+
+<p>Click the button and you'll be prompted for a new <code>.properties</code> file for that add-on. If you provide a new file, the add-on's locale data will be updated with the new file.</p>
+
+<h2 id="Limitations">Limitations</h2>
+
+<p>The current localization support is a first step towards full support, and contains a number of limitations.</p>
+
+<ul>
+ <li>
+ <p>There's no support for content scripts or CSS files: at the moment, you can only localize strings appearing in JavaScript files that can <code>require()</code> SDK modules and in HTML.</p>
+ </li>
+ <li>
+ <p>The set of locale files is global across an add-on. This means that a module isn't able to override a more general translation: so a module <code>informal.js</code> can't specify that "hello_id" occurring in its code should be localized to "Hi!".</p>
+ </li>
+ <li>
+ <p>The SDK tools compile the locale files into a JSON format when producing an XPI. This means that translators can't localize an add-on given the XPI alone, but must be given access to the add-on source.</p>
+ </li>
+ <li>
+ <p>The add-on developer must manually assemble the set of localizable strings that make up the locale files. In a future release we'll add a command to <code>cfx</code> that scans the add-on for localizable strings and builds a template <code>.properties</code> file listing all the strings that need to be translated.</p>
+ </li>
+</ul>
+
+<h2 id="See_Also_-_for_developers_looking_to_localize_non-SDK_add-ons">See Also - for developers looking to localize non-SDK add-ons</h2>
+
+<ul>
+ <li>How to localize html pages, xul files, and js/jsm files from bootstrapped add-ons: <a href="/en-US/Add-ons/Bootstrapped_extensions#Localization_%28L10n%29">Bootstrapped Extensions :: Localization (L10n)</a></li>
+ <li>XUL School Localization Tutorial: <a href="/en-US/docs/Mozilla/Tech/XUL/Tutorial/Localization">DTD/Entities method</a> and <a href="/en-US/docs/Mozilla/Tech/XUL/Tutorial/Property_Files">Properties method</a></li>
+ <li><a href="/en-US/docs/Mozilla/Localization/Localizing_an_extension">Localizing an extension</a></li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/list_open_tabs/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/list_open_tabs/index.html
new file mode 100644
index 0000000000..8a4985806e
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/list_open_tabs/index.html
@@ -0,0 +1,72 @@
+---
+title: 列出打开的标签页
+slug: Mozilla/Add-ons/SDK/Tutorials/List_Open_Tabs
+tags:
+ - Add-on SDK
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/List_Open_Tabs
+---
+<p>{{AddonSidebar}}</p>
+
+<div class="note">
+<p><span>学习本教程之前你需要学习 <a href="/en-US/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29"><code>jpm</code> 基础</a>。</span></p>
+</div>
+
+<p>列出打开的标签页,你可以遍历 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> 对象本身。</p>
+
+<p>下面的 add-on 添加一个 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">action button</a> 当用户单击该按钮时,该日志将在打开的标签页中记录:</p>
+
+<pre class="brush: js">require("sdk/ui/button/action").ActionButton({
+ id: "list-tabs",
+ label: "List Tabs",
+ icon: "./icon-16.png",
+ onClick: listTabs
+});
+
+function listTabs() {
+ var tabs = require("sdk/tabs");
+ for (let tab of tabs)
+ console.log(tab.url);
+}
+</pre>
+
+<div class="note">
+<p>注意:为此你需要一个按钮图标,以"icon-16.png"的文件名保存到你的 add-on 的"data"目录下。你可以从这里下载图标:<img alt="" src="https://mdn.mozillademos.org/files/7649/icon-16.png" style="height: 16px; width: 16px;">。</p>
+</div>
+
+<p>运行该 add-on,加载一对标签页,并点击按钮,你会看到在<a href="/en-US/Add-ons/SDK/Tutorials/Logging">控制台</a>输出如下的内容:</p>
+
+<pre>info: http://www.mozilla.org/en-US/about/
+info: http://www.bbc.co.uk/
+</pre>
+
+<div class="warning">
+<p>你不能直接访问到标签页中的任何宿主内容(具体概念请查阅相关内容:<span class="tcnt">JavaScript 本地对象、内置对象、宿主对象</span> )。</p>
+
+<p>为了访问标签页的内容,你需要使用 tab.attach() 添加一个脚本,此 add-on 加载加载一个页面,然后将一个脚本附加到所有打开的标签页,该脚本将向标签页的文档添加红色边框:</p>
+</div>
+
+<pre class="brush: js">require("sdk/ui/button/action").ActionButton({
+ id: "list-tabs",
+ label: "List Tabs",
+ icon: "./icon-16.png",
+ onClick: listTabs
+});
+
+function listTabs() {
+ var tabs = require("sdk/tabs");
+ for (let tab of tabs)
+ runScript(tab);
+}
+
+function runScript(tab) {
+ tab.attach({
+ contentScript: "document.body.style.border = '5px solid red';"
+ });
+}
+</pre>
+
+<h2 id="学习更多">学习更多</h2>
+
+<p>要了解更多关于SDK中标签如何工作, 查看 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code> API reference</a>。</p>
+
+<p>要了解更多关于在标签中运行脚本, 查看 <a href="/en-US/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">tutorial on using <code>tab.attach()</code></a>。</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/listen_for_page_load/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/listen_for_page_load/index.html
new file mode 100644
index 0000000000..815cfd42c5
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/listen_for_page_load/index.html
@@ -0,0 +1,42 @@
+---
+title: 监听页面加载
+slug: Mozilla/Add-ons/SDK/Tutorials/Listen_for_Page_Load
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Listen_for_Page_Load
+---
+<p>{{AddonSidebar}}</p>
+
+<div class="note"><span>学习本教程之前你需要了解 <a href="/en-US/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29"><code>jpm</code> 基础</a>。</span></div>
+
+<p>你可以使用 <a href="/zh-CN/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> 模块来获取关于新页面加载的通知。下面的附加组件监听标签页内建的 <code>ready</code> 事件,并且记录下每一个标签加载时的URL:</p>
+
+<pre class="brush: js">require("sdk/tabs").on("ready", logURL);
+
+function logURL(tab) {
+ console.log(tab.url);
+}
+</pre>
+
+<div class="note">
+<p>你会在<a href="/zh-CN/docs/Tools/Browser_Console">浏览器控制台</a>,而非 <a href="/zh-CN/docs/Tools/Web_Console">Web 控制台</a>中,找到这些输出的内容。</p>
+</div>
+
+<p>你不能直接访问标签页里面的内容。</p>
+
+<p>为了访问标签页内容,你需要使用 <code>tab.attach()</code> 把一个脚本附到标签页上。这个示例给每一个打开后的标签页附上了一个脚本。这个脚本给标签页的 document 加上了一个红色边框:</p>
+
+<pre class="brush: js">require("sdk/tabs").on("ready", runScript);
+
+function runScript(tab) {
+ tab.attach({
+ contentScript: "if (document.body) document.body.style.border = '5px solid red';"
+ });
+}
+</pre>
+
+<p>(本示例仅仅表示:可以像这样实现一些功能,而你应当使用 <a href="/zh-CN/Add-ons/SDK/High-Level_APIs/page-mod"><code>page-mod</code></a>,并且指定匹配模式为 "*"。)</p>
+
+<h2 id="了解更多">了解更多</h2>
+
+<p>想要了解更多关于如何在SDK中处理标签页的内容,请看 <a href="/zh-CN/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code> API 参考</a>。你能够监听其他一些标签页事件,包括 <code>open</code>、<code>close</code>、和 <code>activate</code>。</p>
+
+<p>想要了解更多关于在标签页中运行脚本的事情,请看 <a href="/en-US/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab"><code>tab.attach() 使用教程</code></a>。</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_the_page_hosted_by_a_tab/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_the_page_hosted_by_a_tab/index.html
new file mode 100644
index 0000000000..5fd51fd8f7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_the_page_hosted_by_a_tab/index.html
@@ -0,0 +1,109 @@
+---
+title: 修改标签页中页面
+slug: Mozilla/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab
+tags:
+ - Add-on SDK
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab
+---
+<div class="note">
+<p>为了进一步学习本教程,你需要安装 <a href="/en-US/Add-ons/SDK/Tutorials/Installation">Add-on SDK</a> 和学习 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_Started_With_cfx">cfx的基本使用</a></p>
+
+<p>这篇教程使用<a href="https://developer.mozilla.org/en-US/Add-ons/SDK/Low-Level_APIs/ui_button_action">动作按钮</a>API,需要Firefox 29或更新版本。</p>
+</div>
+
+<p>为了修改特定标签页中的页面, 可以使用<code> <a href="https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/tabs">tab</a></code>对象的<code>attach()</code> 方法加载一个script脚本到页面中。因为他们的工作是和Web内容进行交互,所以这些脚本被称为content scripts(内容脚本)。</p>
+
+<p>这是个简单的示例:</p>
+
+<pre class="brush: js">var button = require("sdk/ui/button/action").ActionButton({
+  id: "style-tab",
+  label: "Style Tab",
+  icon: "./icon-16.png",
+  onClick: function() {
+    require("sdk/tabs").activeTab.attach({
+      contentScript: 'document.body.style.border = "5px solid red";'
+    });
+  }
+});</pre>
+
+<p>要运行这个示例你必须保存一个名为”icon-16.png“的图标文件在你的Add-on目录下的”data”目录下。你可以下载这个图标: <img alt="" src="https://mdn.mozillademos.org/files/7661/icon-16.png" style="width: 16px; height: 16px;">。</p>
+
+<p>这个插件创建一个按钮,其中包含Mozilla的图标作为一个图标。这个按钮产生一个点击事件处理程序,处理事件中将获取当前活动标签页和加载一个脚本到该标签页中的页面。使用<code>contentscript</code>选项指定加载的脚本,该脚本只绘制一个红色边框页。</p>
+
+<p>然后在浏览器窗口中打开任何网页,点击按钮 。你会看到一个红色的边界出现在页面中, 就像这样:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6531/tabattach-bbc.png" style="display: block; margin-left: auto; margin-right: auto;"></p>
+
+<h2 id="保持Content_Script在一个单独的文件中">保持Content Script在一个单独的文件中</h2>
+
+<p>在上面的例子中我们的<code>content script</code>作为一个字符串来直接使用.除非脚本非常简单,你应该保持脚本作为一个单独的文件。这使得代码更容易维护、调试和审查。</p>
+
+<p>比如,我们把上面的脚本代码保存在Add-on目录下的data目录中并取名为<code>my-script.js</code>,在代码中可以这样加载脚本:</p>
+
+<pre class="brush: js">var self = require("sdk/self");
+
+var button = require("sdk/ui/button/action").ActionButton({
+  id: "style-tab",
+  label: "Style Tab",
+  icon: "./icon-16.png",
+  onClick: function() {
+    require("sdk/tabs").activeTab.attach({
+      contentScriptFile: self.data.url("my-script.js")
+    });
+  }
+});
+</pre>
+
+<p>你可以加载多个脚本,同时这些脚本可以直接相互作用。所以你可以加载 <a href="http://jquery.com/">jQuery</a>, 然后在你的其他 content script使用它。</p>
+
+<h2 id="与Content_Script传递信息">与Content Script传递信息</h2>
+
+<p>你的扩展插件脚本Add-on script和内容脚本content script 不能直接访问对方的变量和函数,但他们之间可以互相发送消息。</p>
+
+<p>从一方发送消息到另外一方, 发送方需要调用 <code>port.emit()发送消息,</code> 同时接收方使用<code>port.on()</code>接收消息。</p>
+
+<ul>
+ <li>在 content script 中, <code>port</code> 是全局对象 <code>self</code> 的属性之一.</li>
+ <li>在 content script 中, <code>tab.attach()</code> 返回一个其中包含 <code>port</code> 属性的 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_worker">worker</a> 对象,你可以使用它来向 content script 发送消息</li>
+</ul>
+
+<p>让我们重写上面的例子来从附加内容脚本 content script 传递一个消息。现在content script 需要像下面这样:</p>
+
+<pre class="brush: js">// "self" is a global object in content scripts
+// Listen for a "drawBorder"
+self.port.on("drawBorder", function(color) {
+ document.body.style.border = "5px solid " + color;
+});
+</pre>
+
+<p>在 add-on script 扩展脚本中,我们使用 <code>attach()方法返回的对象向 content script</code> 中发送一个“drawBorder”消息:</p>
+
+<pre class="brush: js">var self = require("sdk/self");
+var tabs = require("sdk/tabs");
+
+var button = require("sdk/ui/button/action").ActionButton({
+  id: "style-tab",
+  label: "Style Tab",
+  icon: "./icon-16.png",
+  onClick: function() {
+    var worker = tabs.activeTab.attach({
+      contentScriptFile: self.data.url("my-script.js")
+    });
+    worker.port.emit("drawBorder", "red");
+  }
+});
+</pre>
+
+<p>名为 <code>drawBorder</code> 的消息并不是一个内置的消息, 而是通过 <code>port.emit()方法自定义的。</code></p>
+
+<h2 id="注入_CSS">注入 CSS</h2>
+
+<p>不像 <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod"><code>page-mod</code></a> API, <code>tab.attach()</code> 不允许你直接注入CSS到页面中。</p>
+
+<p>你需要使用 JavaScript 来修改页面的样式,就像前面的示例那样。</p>
+
+<h2 id="学习更多">学习更多</h2>
+
+<p>要了解更多关于在SDK中标签页的使用, 可以查看<a href="/en-US/Add-ons/SDK/Tutorials/Open_a_Web_Page">打开一个网页</a>教程,  <a href="/en-US/Add-ons/SDK/Tutorials/List_Open_Tabs">列出打开的标签页</a>教程, 和<a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code> API 参考手册</a>.</p>
+
+<p>要学习更多关于content scripts, 查看 <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">content scripts guide</a>.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_web_pages_based_on_url/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_web_pages_based_on_url/index.html
new file mode 100644
index 0000000000..6e5e46c532
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/modifying_web_pages_based_on_url/index.html
@@ -0,0 +1,210 @@
+---
+title: Modifying Web Pages Based on URL
+slug: Mozilla/Add-ons/SDK/Tutorials/Modifying_Web_Pages_Based_on_URL
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Modifying_Web_Pages_Based_on_URL
+---
+<div class="note">开始本教程之前,您必须安装好 <em><strong>SDK</strong></em>,并且学习 <strong><em>cfx </em></strong>的基本的使用方法。</div>
+
+<p>要修改任何页面匹配特定的模式(比如,“http://example.org/”)当它们加载后,使用<a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a>模块。</p>
+
+<p>要创建 <strong><em>page-mod</em></strong>,您必须指定两件事:</p>
+
+<ul>
+ <li>一个或多个 <em><strong>content scripts</strong></em> 运行,它们的工作将和网站内容进行交互</li>
+ <li>一个或多个 <strong><em>patterns</em> </strong>去匹配您要修改的页面的 URLs</li>
+</ul>
+
+<div class="note">
+<p>content scripts为内容脚本,只能使用普通浏览器支持的 JS,不能使用 add-on 的API</p>
+</div>
+
+<p>这里有一个范例。内容脚本提供contentScript选项,地址样本提供include选项:</p>
+
+<pre class="brush: js">// Import the page-mod API
+var pageMod = require("sdk/page-mod");
+
+// Create a page mod
+// It will run a script whenever a ".org" URL is loaded
+// The script replaces the page contents with a message
+pageMod.PageMod({
+ include: "*.org",
+ contentScript: 'document.body.innerHTML = ' +
+ ' "&lt;h1&gt;Page matches ruleset&lt;/h1&gt;";'
+});
+</pre>
+
+<p>试试吧:</p>
+
+<ul>
+ <li>创建新的目录并转到该目录下</li>
+ <li>运行 <code>cfx init</code></li>
+ <li>打开 <code>lib/main.js</code> 文件,添加以上的代码</li>
+ <li>运行 <code>cfx run</code></li>
+ <li>在打开的浏览器窗口中打开 <a href="http://www.ietf.org">ietf.org</a></li>
+</ul>
+
+<p>您将看到:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/6537/pagemod-ietf.png" style="display: block; margin-left: auto; margin-right: auto;"></p>
+
+<h2 id="指定匹配模式">指定匹配模式</h2>
+
+<p>匹配模式使用 <a href="/en-US/Add-ons/SDK/Low-Level_APIs/util_match-pattern"><code>match-pattern</code></a> 语法。您可以通过单一的匹配字符串,或者数组。</p>
+
+<h2 id="把内容脚本放在独立的文件中">把内容脚本放在独立的文件中</h2>
+
+<p>在上面的范例中我们通过字符串来实现内容脚本。除非是用作简单的例子,通常情况下您应该将内容脚本放在独立文件中,这将使您的代码更易维护、调式和查看。</p>
+
+<p>要这样做,您需要:</p>
+
+<ul>
+ <li>将脚本文件保存在 data 目录下</li>
+ <li>使用 <code>contentScriptFile</code> 选项代替 <code>contentScript 选项,并且指定脚本的路径</code>。路径用 <code>self.data.url()</code> 取得</li>
+</ul>
+
+<p>例如,如果我们将内容脚本保存在 data 目录下,命名为 my-script.js,在main.js中,我们应该这么写:</p>
+
+<pre class="brush: js">// Import the page-mod API
+var pageMod = require("sdk/page-mod");
+// Import the self API
+var self = require("sdk/self");
+
+// Create a page mod
+// It will run a script whenever a ".org" URL is loaded
+// The script replaces the page contents with a message
+pageMod.PageMod({
+ include: "*.org",
+ contentScriptFile: self.data.url("my-script.js")
+});</pre>
+
+<h2 id="加载多个Content_Scripts">加载多个Content Scripts</h2>
+
+<p>您可以加载更多脚本,且脚本可以相互交互。所以,您可以使用jQuery重写 my-script.js:</p>
+
+<pre class="brush: js">$("body").html("&lt;h1&gt;Page matches ruleset&lt;/h1&gt;");
+</pre>
+
+<p>然后下载 jQuery 库到您的扩展开发目录的 data 目录下,并且将 jQuery 和 my-script 一起加载(确保先加载 jQuery 库):</p>
+
+<pre class="brush: js">// Import the page-mod API,加载 add-on 的 page-mod API
+var pageMod = require("sdk/page-mod");
+// Import the self API, 加载 add-on 的 self API
+var self = require("sdk/self");
+
+// Create a page mod
+// It will run a script whenever a ".org" URL is loaded
+// The script replaces the page contents with a message
+// 创建 page mod,匹配 “.org” URL
+pageMod.PageMod({
+ include: "*.org",
+ contentScriptFile: [self.data.url("jquery-1.7.min.js"), self.data.url("my-script.js")]
+});
+</pre>
+
+<p>您也可以在同一 page-mod 中同时使用 <code>contentScript</code> 和 <code>contentScriptFile</code> 。如果您这么做的话,contentScript的脚本将会先加载。(应该是contentScriptFile的先加载吧?)</p>
+
+<pre class="brush: js">// Import the page-mod API
+var pageMod = require("sdk/page-mod");
+// Import the self API
+var self = require("sdk/self");
+
+// Create a page mod
+// It will run a script whenever a ".org" URL is loaded
+// The script replaces the page contents with a message
+pageMod.PageMod({
+ include: "*.org",
+ contentScriptFile: self.data.url("jquery-1.7.min.js"),
+ contentScript: '$("body").html("&lt;h1&gt;Page matches ruleset&lt;/h1&gt;");'
+});
+</pre>
+
+<p>注意,您不能直接加载网站上的脚本。脚本必须从 data 目录中加载。</p>
+
+<h2 id="与_Content_Script_通信">与 Content Script 通信</h2>
+
+<p>Your add-on script and the content script can't directly access each other's variables or call each other's functions, but they can send each other messages.</p>
+
+<p>从 Content Script 与 main.js 通信,发送方使用 <code>port.emit()</code> ,接收方使用 <code>port.on()</code> 监听.</p>
+
+<ul>
+ <li>In the content script, <code>port</code> is a property of the global <code>self</code> object.</li>
+ <li>In the add-on script, you need to listen for the <code>onAttach</code> event to get passed a <a href="/en-US/Add-ons/SDK/Low-Level_APIs/content_worker">worker</a> object that contains <code>port</code>.</li>
+</ul>
+
+<p>Let's rewrite the example above to pass a message from the add-on to the content script. The message will contain the new content to insert into the document. The content script now needs to look like this:</p>
+
+<pre class="brush: js">// "self" is a global object in content scripts
+// Listen for a message, and replace the document's
+// contents with the message payload.
+self.port.on("replacePage", function(message) {
+ document.body.innerHTML = "&lt;h1&gt;" + message + "&lt;/h1&gt;";
+});
+</pre>
+
+<p>In the add-on script, we'll send the content script a message inside <code>onAttach</code>:</p>
+
+<pre class="brush: js">// Import the page-mod API
+var pageMod = require("sdk/page-mod");
+// Import the self API
+var self = require("sdk/self");
+
+// Create a page mod
+// It will run a script whenever a ".org" URL is loaded
+// The script replaces the page contents with a message
+pageMod.PageMod({
+ include: "*.org",
+ contentScriptFile: self.data.url("my-script.js"),
+ // Send the content script a message inside onAttach
+ onAttach: function(worker) {
+ worker.port.emit("replacePage", "Page matches ruleset");
+ }
+});
+</pre>
+
+<p>The <code>replacePage</code> message isn't a built-in message: it's a message defined by the add-on in the <code>port.emit()</code> call.</p>
+
+<h2 id="注入_CSS">注入 CSS</h2>
+
+<div class="warning">
+<p><strong>请注意,本节中描述的功能是实验性的:我们很可能继续支持的功能,但可能需要改变的细节。</strong></p>
+</div>
+
+<p>Rather than injecting JavaScript into a page, you can inject CSS by setting the page-mod's <code>contentStyle</code> option:</p>
+
+<pre class="brush: js">var pageMod = require("sdk/page-mod").PageMod({
+ include: "*",
+ contentStyle: "body {" +
+ " border: 5px solid green;" +
+ "}"
+});
+</pre>
+
+<p>As with <code>contentScript</code>, there's a corresponding <code>contentStyleFile</code> option that's given the URL of a CSS file in your "data" directory, and it is good practice to use this option in preference to <code>contentStyle</code> if the CSS is at all complex:</p>
+
+<pre class="brush: js">var pageMod = require("sdk/page-mod").PageMod({
+ include: "*",
+ contentStyleFile: require("sdk/self").data.url("my-style.css")
+});
+</pre>
+
+<p>You can't currently use relative URLs in style sheets loaded with <code>contentStyle</code> or <code>contentStyleFile</code>. If you do, the files referenced by the relative URLs will not be found.</p>
+
+<p>To learn more about this, and read about a workaround, see the <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod#PageMod(options)">relevant section in the page-mod API documentation</a>.</p>
+
+<h2 id="Learning_More">Learning More</h2>
+
+<p>To learn more about <code>page-mod</code>, see its <a href="/en-US/Add-ons/SDK/High-Level_APIs/page-mod">API reference page</a>. In particular, the <code>PageMod</code> constructor takes several additional options to control its behavior:</p>
+
+<ul>
+ <li>
+ <p>By default, content scripts are not attached to any tabs that are already open when the page-mod is created, and are attached to iframes as well as top-level documents. To control this behavior use the <code>attachTo</code> option.</p>
+ </li>
+ <li>
+ <p>Define read-only values accessible to content scripts using the <code>contentScriptOptions</code> option.</p>
+ </li>
+ <li>
+ <p>By default, content scripts are attached after all the content (DOM, JS, CSS, images) for the page has been loaded, at the time the <a href="/en-US/docs/Web/API/GlobalEventHandlers.onload">window.onload event</a> fires. To control this behavior use the <code>contentScriptWhen</code> option.</p>
+ </li>
+</ul>
+
+<p>To learn more about content scripts in general, see the <a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">content scripts guide</a>.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/open_a_web_page/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/open_a_web_page/index.html
new file mode 100644
index 0000000000..7ff9ba7883
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/open_a_web_page/index.html
@@ -0,0 +1,52 @@
+---
+title: 打开Web页面
+slug: Mozilla/Add-ons/SDK/Tutorials/Open_a_Web_Page
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Open_a_Web_Page
+---
+{{AddonSidebar}}
+
+<div class="note"><span>学习本教程之前你需要学习 <a href="/zh-CN/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29"><code>jpm</code> 基础</a>。</span></div>
+
+<p>打开一个新的网页,你可以使用 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code></a> 模块:</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+tabs.open({
+"http://www.example.com");
+</pre>
+
+<p>这个函数是异步的,所以你不能立即获取一个可以检查的标签对象。要做到这一点,通过一个回调函数为open()。将回调函数赋值给 onready 属性,并将通过标签作为参数:</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+tabs.open({
+ url: "http://www.example.com",
+ onReady: function onReady(tab) {
+ console.log(tab.title);
+ }
+});
+</pre>
+
+<div class="warning">
+<p>尽管这样,你还是不能直接访问到标签页中的任何宿主内容(具体概念请查阅相关内容:<span class="tcnt">JavaScript 本地对象、内置对象、宿主对象</span> )。</p>
+</div>
+
+<p>
+要访问标签页的内容,你需要使用 tab.attach()把一个脚本添加到该标签页。此add-on加载加载一个页面,然后将一个脚本附加到该页,该将向页面添加红色边框:</p>
+
+<pre class="brush: js">var tabs = require("sdk/tabs");
+tabs.open({
+ url: "http://www.example.com",
+ onReady: runScript
+});
+
+function runScript(tab) {
+ tab.attach({
+ contentScript: "document.body.style.border = '5px solid red';"
+ });
+}
+</pre>
+
+<h2 id="学习更多">学习更多</h2>
+
+<p>要了解更多关于SDK中标签如何工作, 查看 <a href="/en-US/Add-ons/SDK/High-Level_APIs/tabs"><code>tabs</code> API reference</a>.</p>
+
+<p>要了解更多关于在标签中运行脚本, 查看 <a href="/en-US/Add-ons/SDK/Tutorials/Modifying_the_Page_Hosted_by_a_Tab">tutorial on using <code>tab.attach()</code></a>.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/troubleshooting/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/troubleshooting/index.html
new file mode 100644
index 0000000000..afa3cc0cd3
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/troubleshooting/index.html
@@ -0,0 +1,39 @@
+---
+title: Troubleshooting
+slug: Mozilla/Add-ons/SDK/Tutorials/Troubleshooting
+tags:
+ - add-on sdk 安装指南
+ - add-on sdk安装解惑
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Troubleshooting
+---
+<p>{{AddonSidebar}}</p>
+
+<p>如果你的SDK安装和运行遇到了问题,不要慌!本页面列出了一些基本点,来帮助你追踪你的问题。</p>
+
+<h2 id="检查你的_Firefox">检查你的 Firefox</h2>
+
+<p><code>jpm</code> 会搜索你系统中 Firefox 常见的地址,<code>jpm</code> 也许不能找到火狐安装在哪,或者你有多个地方安装了火狐,<code>jpm</code> 也许找错了地方。这种情况下,你需要使用 <code>jpm</code> 的 <code>--binary</code> 选项。参看 <code><a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a></code> 指南以获取更多信息</p>
+
+<p>当你运行 <code>jpm</code> 来测试你的 add-on 或者运行单元测试时,它会打印出 Firefox 或 XULRunner 二进制文件的地址,所有你可以检查一下它的输出内容来做确认。</p>
+
+<h2 id="检查你的文本控制台">检查你的文本控制台</h2>
+
+<p>当你的代码代码和SKD的API产生错误时,他们会被记录到文本控制台。这应该和你运行 <code>jpm</code> 命令的是同一控制台或shell</p>
+
+<h2 id="搜索已知的问题">搜索已知的问题</h2>
+
+<p>也许有人已经遇到过和你一样的问题了。其他用户经常发布问题到 <a href="http://groups.google.com/group/mozilla-labs-jetpack/topics">项目邮件列表</a>。你也可以浏览<a href="https://bugzilla.mozilla.org/buglist.cgi?order=Bug%20Number&amp;resolution=---&amp;resolution=DUPLICATE&amp;query_format=advanced&amp;product=Add-on%20SDK">已知问题</a>列表或者<a href="https://bugzilla.mozilla.org/query.cgi?format=advanced&amp;product=Add-on%20SDK">搜索</a>特定的关键词。</p>
+
+<h2 id="与项目团队和用户组交流">与项目团队和用户组交流</h2>
+
+<p>SDK的用户和项目团队成员对问题和建议在 <a href="http://groups.google.com/group/mozilla-labs-jetpack/topics">项目的邮件列表</a>.  别人可能有与你相同的问题,所以试着搜索列表。也欢迎你发表问题.</p>
+
+<p>你也可以与其他SDK用户在 <a href="http://irc.mozilla.org/">Mozilla的 IRC 网络</a> 的 <a href="http://mibbit.com/?channel=%23jetpack&amp;server=irc.mozilla.org">#jetpack</a> 聊天室聊天.</p>
+
+<p>如果你想<a href="https://bugzilla.mozilla.org/enter_bug.cgi?product=Add-on%20SDK&amp;component=General">报告SDK的bug</a><span>,我们非常欢迎!您将需要创建一个 Bugzilla 的帐号,Bugzilla 是 Mozilla 的 bug 追踪系统。</span></p>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
+
+<div id="xunlei_com_thunder_helper_plugin_d462f475-c18e-46be-bd10-327458d045bd"> </div>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/unit_testing/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/unit_testing/index.html
new file mode 100644
index 0000000000..63cd86da13
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/unit_testing/index.html
@@ -0,0 +1,102 @@
+---
+title: Unit Testing
+slug: Mozilla/Add-ons/SDK/Tutorials/Unit_testing
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Unit_testing
+---
+<div class="note">
+ <p><span>学习本教程你将需要<a href="/en-US/Add-ons/SDK/Tutorials/Installation">安装SDK</a>, 学习 <a href="/en-US/Add-ons/SDK/Tutorials/Getting_Started_With_cfx">基本操作<code>cfx</code></a>,和学习过<a href="/en-US/Add-ons/SDK/Tutorials/Creating_reusable_modules">编写可重复模块(writing reusable modules)</a>.</span></p>
+</div>
+<div class="note">
+ <p>如果你在使用 <a href="/en-US/Add-ons/SDK/Tools/jpm">jpm</a> 而不是 cfx, 请看关于cfx, 而且重点看<a href="/en-US/Add-ons/SDK/Tools/cfx_to_jpm#Requiring_modules_from_test_code">加载测试模块(loading modules from test code)</a>.</p>
+</div>
+<p>SDK提供了一个框架,为你的代码创建和运行单元测试.接下来我们将演示如何写一个关于<a href="http://en.wikipedia.org/wiki/Base64">Base64</a> 模块的单元测试.</p>
+<h2 id="一个Base64模块例子">一个Base64模块例子</h2>
+<p>在一个网页中, 你可以进行Base64的加密和解密,通过使用函数<code>btoa()</code> and <code>atob()</code> .不幸的是这些函数依附在<code>window</code>对象: 由于这个对象在你的add-on(插件) main 的代码里不是有效对象,所以 <code>atob()</code> and <code>btoa()</code> 也不是有效的. 因此我们将展示如何在这个平台上创建一个<code>base64</code>模块 .</p>
+<p>To begin with, create a new directory, navigate to it, and run <code>cfx init</code>. Now create a new file in "lib" called "base64.js", and give it the following contents:</p>
+<pre class="brush: js">const { atob, btoa } = require("chrome").Cu.import("resource://gre/modules/Services.jsm", {});
+
+exports.atob = a =&gt; atob(a);
+exports.btoa = b =&gt; btoa(b);
+</pre>
+<p>This code exports two functions, which just call the platform's <code>btoa()</code> and <code>atob()</code> functions. To show the module in use, edit the "main.js" file as follows:</p>
+<pre class="brush: js">var base64 = require("./base64");
+
+var button = require("sdk/ui/button/action").ActionButton({
+  id: "base64",
+  label: "base64",
+  icon: "./icon-16.png",
+  onClick: function() {
+    encoded = base64.btoa("hello");
+    console.log(encoded);
+    decoded = base64.atob(encoded);
+    console.log(decoded);
+  }
+});</pre>
+<p>To run this example you'll also have to have an icon file named "icon-16.png" saved in your add-ons "data" directory. You could download this icon: <img alt="" src="https://mdn.mozillademos.org/files/7661/icon-16.png" style="width: 16px; height: 16px;">.</p>
+<p>Now "main.js" imports the base64 module and calls its two exported functions. If we run the add-on and click the button, we should see the following logging output:</p>
+<pre>info: aGVsbG8=
+info: hello
+</pre>
+<h2 id="Testing_the_Base64_Module">Testing the Base64 Module</h2>
+<p>Navigate to the add-on's <code>test</code> directory and delete the <code>test-main.js</code> file. In its place create a file called <code>test-base64.js</code> with the following contents:</p>
+<pre class="brush: js">var base64 = require("./base64");
+
+exports["test atob"] = function(assert) {
+ assert.ok(base64.atob("aGVsbG8=") == "hello", "atob works");
+}
+
+exports["test btoa"] = function(assert) {
+ assert.ok(base64.btoa("hello") == "aGVsbG8=", "btoa works");
+}
+
+exports["test empty string"] = function(assert) {
+ assert.throws(function() {
+ base64.atob();
+ },
+ "empty string check works");
+}
+
+require("sdk/test").run(exports);
+</pre>
+<p>This file: exports three functions, each of which expects to receive a single argument which is an <code>assert</code> object. <code>assert</code> is supplied by the <a href="/en-US/Add-ons/SDK/Low-Level_APIs/test_assert"><code>test/assert</code></a> module and implements the <a href="http://wiki.commonjs.org/wiki/Unit_Testing/1.1">CommonJS Unit Testing specification</a>.</p>
+<ul>
+ <li>
+ <p>The first two functions call <code>atob()</code> and <code>btoa()</code> and use <a href="/en-US/Add-ons/SDK/Low-Level_APIs/test_assert#ok(guard.2C_message)"><code>assert.ok()</code></a> to check that the output is as expected.</p>
+ </li>
+ <li>
+ <p>The second function tests the module's error-handling code by passing an empty string into <code>atob()</code> and using <a href="/en-US/Add-ons/SDK/Low-Level_APIs/test_assert#throws(block.2C_error.2C_message)"><code>assert.throws()</code></a> to check that the expected exception is raised.</p>
+ </li>
+</ul>
+<p>At this point your add-on ought to look like this:</p>
+<pre> /base64
+ package.json
+ README.md
+ /doc
+ main.md
+ /lib
+ main.js
+ base64.js
+ /test
+ test-base64.js
+</pre>
+<p>Now execute <code>cfx --verbose test</code> from the add-on's root directory. You should see something like this:</p>
+<pre>Running tests on Firefox 13.0/Gecko 13.0 ({ec8030f7-c20a-464f-9b0e-13a3a9e97384}) under darwin/x86.
+info: executing 'test-base64.test atob'
+info: pass: atob works
+info: executing 'test-base64.test btoa'
+info: pass: btoa works
+info: executing 'test-base64.test empty string'
+info: pass: empty string check works
+
+3 of 3 tests passed.
+Total time: 5.172589 seconds
+Program terminated successfully.
+</pre>
+<p>What happens here is that <code>cfx test</code>:</p>
+<p><span>Note the hyphen after "test" in the module name. <code>cfx test</code> will include a module called "test-myCode.js", but will exclude modules called "test_myCode.js" or "testMyCode.js".</span></p>
+<ul>
+ <li>looks in the <code>test</code> directory of your package</li>
+ <li>loads any modules whose names start with the word <code>test-</code></li>
+ <li>calls each exported function whose name starts with "test", passing it an <a href="/en-US/Add-ons/SDK/Low-Level_APIs/test_assert#Assert"><code>assert</code></a> object as its only argument.</li>
+</ul>
+<p>Obviously, you don't have to pass the <code>--verbose</code> option to <code>cfx</code> if you don't want to; doing so just makes the output easier to read.</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/日志/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/日志/index.html
new file mode 100644
index 0000000000..e581a0811c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/日志/index.html
@@ -0,0 +1,62 @@
+---
+title: 日志
+slug: Mozilla/Add-ons/SDK/Tutorials/日志
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Logging
+---
+<p>{{AddonSidebar}}</p>
+
+<div class="note"><span>学习本教程之前你需要学习 </span><span><a href="/en-US/docs/Mozilla/Add-ons/SDK/Tutorials/Getting_Started_%28jpm%29">jpm 基础</a>. </span></div>
+
+<p><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); display: inline !important; float: none; font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><a href="https://developer.mozilla.org/en/DOM/console">DOM console</a> 对象对调试 Javascript 非常有帮助。但是由于扩展程序无法访问 DOM 对象,sdk 提供了一个拥有大部分 DOM console 对象方法的全局 console 对象,包括打印错误日车、警告和数据信息的方法。你无需 require() 任何模块,就可以直接使用 console 对象。</span></p>
+
+<p><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); display: inline !important; float: none; font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;">使用 console.log() 方法来打印信息:</span></p>
+
+<pre class="brush: js">console.log("Hello World");
+</pre>
+
+<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-line" style="display: block; width: 516px;"><span class="md-expand" style="">尝试:</span></span></p>
+
+<ul style="margin: -1em 0px 1.5em 1.5em; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;">
+ <li style="margin: 0px; position: relative; list-style-type: disc;">
+ <p style="margin: 0.5rem 0px; width: inherit; position: relative;"><span class="md-line" style="display: block; width: 452px;"><span style="">新建一个目录,打开它</span></span></p>
+ </li>
+ <li style="margin: 0px; position: relative; list-style-type: disc;">
+ <p style="margin: 0.5rem 0px; width: inherit; position: relative;"><span class="md-line" style="display: block; width: 452px;"><span style="">执行 </span><span style=""><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm init</code></span><span style="">,接受所有默认设置</span></span></p>
+ </li>
+ <li style="margin: 0px; position: relative; list-style-type: disc;">
+ <p style="margin: 0.5rem 0px; width: inherit; position: relative;"><span class="md-line" style="display: block; width: 452px;"><span style="">打开 "index.js",并在文件内添加上面的代码</span></span></p>
+ </li>
+ <li style="margin: 0px; position: relative; list-style-type: disc;">
+ <p style="margin: 0.5rem 0px; width: inherit; position: relative;"><span class="md-focus md-line" style="display: block; width: 452px;"><span style="">执行 </span><span style=""><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm run</code></span></span></p>
+ </li>
+</ul>
+
+<p><span class="md-expand" style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;">Firefox 将会启动,并在你执行 </span><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm run</code></span><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"> 的命令行窗口显示下面的信息:</span></p>
+
+<pre>console.log: console: Hello world
+</pre>
+
+<h2 id="在内容脚本(conent_script)中使用_console"><code>在内容脚本(conent script)中使用 console</code></h2>
+
+<p><span class="md-expand" style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;">与 addon 主代码一样,你可以在<a href="/en-US/Add-ons/SDK/Guides/Content_Scripts">内容脚本</a>中直接使用 console 对象。下面这个扩展在内容脚本中调用了 </span><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">console.log()</code></span><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"> 方法,作用是在控制台打印出每个打开的标签页内的 HTML 内容:</span></p>
+
+<pre class="brush: js">require("sdk/tabs").on("ready", function(tab) {
+ tab.attach({
+ contentScript: "console.log(document.body.innerHTML);"
+ });
+});
+</pre>
+
+<h2 id="控制台输出"><span style="">控制台输出</span></h2>
+
+<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-line" style="display: block; width: 516px;"><span style="">如果你是在命令行启动你的扩展(例如:执行 </span><span style=""><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm run</code></span><span style=""> 或 </span><span style=""><code style="font-family: monospace, monospace; font-size: 0.875em; text-align: left; padding-left: 1ch; padding-right: 1ch; line-height: 1.71428em; background-color: rgb(218, 218, 218);">jpm test</code></span><span style="">),那么控制台信息将在你使用的命令行界面中显示。</span></span></p>
+
+<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-line" style="display: block; width: 516px;"><span style="">如果你将扩展安装到了 Firefox 中,控制台信息将显示在 Firefox <a href="/en-US/docs/Tools/Browser_Console">浏览器控制台</a>中。</span></span></p>
+
+<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-line" style="display: block; width: 516px;"><span style="">但请注意,<strong>默认情况下,任何已经安装的扩展不会在错误控制台中输出任何信息</strong>,包括使用扩展构建程序安装的扩展或者使用其它工具例如:<a href="https://addons.mozilla.org/en-US/firefox/addon/autoinstaller/">Extension Auto-installer</a>。</span></span></p>
+
+<p style="margin-bottom: 1.5em; width: inherit; position: relative; color: rgb(31, 9, 9); font-family: 'PT Serif', 'Times New Roman', Times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;"><span class="md-focus md-line" style="display: block; width: 516px;"><span style="">关于此项内容的更多信息请参阅控制台参考文档 “<a href="/en-US/Add-ons/SDK/Tools/console#Logging_Levels">日志等级</a>”。</span></span></p>
+
+<h2 id="更多">更多</h2>
+
+<p><span style="background-color: rgb(243, 242, 238); color: rgb(31, 9, 9); display: inline !important; float: none; font-family: pt serif,times new roman,times; font-size: 16px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: 24px; text-align: start; text-indent: 0px; text-transform: none; white-space: pre-wrap;">完整的 console API,请看 </span> <a href="/en-US/Add-ons/SDK/Tools/console">API 参考文档</a>。</p>
diff --git a/files/zh-cn/mozilla/add-ons/sdk/tutorials/添加一个菜单项/index.html b/files/zh-cn/mozilla/add-ons/sdk/tutorials/添加一个菜单项/index.html
new file mode 100644
index 0000000000..77d743e806
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/sdk/tutorials/添加一个菜单项/index.html
@@ -0,0 +1,49 @@
+---
+title: 添加菜单项
+slug: Mozilla/Add-ons/SDK/Tutorials/添加一个菜单项
+translation_of: Archive/Add-ons/Add-on_SDK/Tutorials/Add_a_Context_Menu_Item
+---
+<div class="note">
+ <p>学习本章前,您要先 <a href="/en-US/Add-ons/SDK/Installation">安装SDK</a> 和学习 <a href="/en-US/Add-ons/SDK/Getting_Started_With_cfx"><code>cfx</code>的基本用法 </a></p>
+</div>
+<p>用<a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu"><code>右键菜单</code></a>模块添加右键菜单项或子菜单</p>
+<p>下面的例子是增加了一个新的上下文菜单项。当页面被选中时才会显示该菜单项,选择的部分会被发送到main.js的add-on代码中,它只是记录:</p>
+<pre class="brush: js">var contextMenu = require("sdk/context-menu");
+ var menuItem = contextMenu.Item({
+ label: "Log Selection",
+ context: contextMenu.SelectionContext(),
+ contentScript: 'self.on("click", function () {' +
+ ' var text = window.getSelection().toString();' +
+ ' self.postMessage(text);' +
+ '});',
+ onMessage: function (selectionText) {
+ console.log(selectionText);
+ }
+});</pre>
+<p>Try it: run the add-on, load a web page, select some text and right-click. You should see the new item appear:</p>
+<p>试一试:运行该扩展,加载一个网页,选中一些文本并右键单击。你应该能看到新的项目出现:</p>
+<p><img src="https://mdn.mozillademos.org/files/6513/context-menu-selection.png" style="display: block; margin-left: auto; margin-right: auto;"></p>
+<p>点击,选中的文本<a href="/en-US/Add-ons/SDK/Tutorials/Logging">记录到控制台</a>:</p>
+<pre>info: elephantine lizard
+</pre>
+<h2 id="细节">细节</h2>
+<p><br>
+ 这个add-on所有的操作是构建一个上下文菜单项。你不需要添加它:一旦你已经建立了项目,它会自动添加在正确的上下文。在这种情况下,构造函数接受四个选项:<code>label</code>,<code>context</code>,和contentscript,onMessage。</p>
+<h3 id="label">label</h3>
+<p><br>
+ 标签是字符串的显示。</p>
+<h3 id="context">context</h3>
+<p><br>
+ 上下文应该在不同的情境中显示它该做的显示。上下文菜单模块提供了一些简单的内置的上下文,包括selectioncontext(),这意味着:当页面被选中的时候将会显示菜单项。<br>
+ 如果这些简单的背景是不够的,你可以使用脚本定义更复杂的环境。</p>
+<h3 id="contentScript">contentScript</h3>
+<p>这将一个脚本项目。在这种情况下,脚本侦听用户点击该项目,然后选定文本用消息发送到add-on。</p>
+<h3 id="onMessage">onMessage</h3>
+<p>onMessage属性提供附加的代码来响应来自连接到上下文菜单项脚本报文的一种方法。在这种情况下,它只是记录选定的文本。</p>
+<p>所以:<br>
+ 用户点击项目<br>
+ 内容脚本的点击事件触发,和内容脚本检索选定的文本和发送邮件的附件<br>
+ 附加的消息事件触发,并附加代码的处理函数是通过选定的文本,它的日志<br>
+  </p>
+<h2 id="获取更多">获取更多</h2>
+<p>如果想获取更多信息关于<code>context-menu</code>模块,查看<a href="/en-US/Add-ons/SDK/High-Level_APIs/context-menu"><code>context-menu</code> API reference</a>.</p>
diff --git a/files/zh-cn/mozilla/add-ons/setting_up_extension_development_environment/index.html b/files/zh-cn/mozilla/add-ons/setting_up_extension_development_environment/index.html
new file mode 100644
index 0000000000..9790442e3c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/setting_up_extension_development_environment/index.html
@@ -0,0 +1,58 @@
+---
+title: 扩展开发环境设置
+slug: Mozilla/Add-ons/Setting_up_extension_development_environment
+tags:
+ - Extensions
+translation_of: Archive/Add-ons/Setting_up_extension_development_environment
+---
+<p>本文给出了关于如何为扩展开发配置Mozilla应用程序的建议.</p>
+<h2 id=".E5.BC.80.E5.8F.91.E9.85.8D.E7.BD.AE" name=".E5.BC.80.E5.8F.91.E9.85.8D.E7.BD.AE">开发配置</h2>
+<p>为了避免由于设置了开发相关的预定义选项导致的性能上的问题,以及避免破坏你的个人数据,建议你可以创建一个新的Profile,而不是使用默认的进行开发工作.</p>
+<p>如果你使用<code>-no-remote</code>参数启动Firefox,你可以用不同的Profile运行两个Firefox实例.例如,不管是否"正常"的Firefox是否运行,下面的命令将运行你的开发Profile(假设你的开发Profile命名为"dev").</p>
+<pre class="eval">start "" "%ProgramFiles%\Mozilla Firefox\firefox.exe" -no-remote -P dev
+</pre>
+<p>用默认的Profile允许Firefox通常仅仅是"firefox"或者"firefox -P default".</p>
+<p>你可以使用Firefox稳定版本和开发版本来检查扩展的兼容性(<a class="external" href="http://forums.mozillazine.org/viewtopic.php?t=613873">Installing Firefox 3 or Minefield while keeping Firefox 2</a>).</p>
+<h2 id=".E5.BC.80.E5.8F.91.E9.A2.84.E5.AE.9A.E4.B9.89.E9.80.89.E9.A1.B9" name=".E5.BC.80.E5.8F.91.E9.A2.84.E5.AE.9A.E4.B9.89.E9.80.89.E9.A1.B9">开发预定义选项</h2>
+<p>这些已定义参数使在低性能的情况下使调试更容易.</p>
+<p>查看<a class="external" href="http://www.mozilla.org/support/firefox/edit">编辑配置文件</a>关于设置预定义选项的信息.注意某些设置默认不存在与abount:config中.所以你需要创建一个新的(boolean)的项.</p>
+<p>要这样做, 添加下面的代码行到你的Profile目录的 <code>user.js</code> 文件中,如果文件不存在,创建之:</p>
+<pre class="eval">user_pref("nglayout.debug.disable_xul_cache",true);
+user_pref("browser.dom.window.dump.enabled",true);
+</pre>
+<p>注意: 对于Firefox 版本 3.0"user.js" 已被 "prefs.js" 替换.</p>
+<p>See below under "Development Profile" to setup a separate development profile before you make these changes.</p>
+<ul>
+ <li><strong>javascript.options.showInConsole</strong> = <strong>true</strong>. Logs errors in chrome files to the <a href="/cn/Error_Console" title="cn/Error_Console">Error Console</a>.</li>
+ <li><strong>nglayout.debug.disable_xul_cache</strong> = <strong>true</strong>. Disables the XUL cache so that changes to windows and dialogs do not require a restart. This assumes you're <a href="#Using_directories_rather_than_JARs">using directories rather than JARs</a>. Changes to XUL overlays will still require reloading of the document overlaid.</li>
+ <li><strong>browser.dom.window.dump.enabled</strong> = <strong>true</strong>. Enables the use of the dump() statement to print to the standard console. See {{ Domxref("window.dump") }} for more info. You can also use {{ Interface("nsIConsoleService") }} from privileged script.</li>
+ <li><strong>javascript.options.strict</strong> = <strong>true</strong>. Enables strict JavaScript warnings in the Error Console. Note that since many people have this setting turned off when developing, you will see lots of warnings for problems with their code in addition to warnings for your own extension. You can filter those with <a class="link-https" href="https://addons.mozilla.org/en-US/firefox/addon/1815">Console<sup>2</sup></a>.</li>
+ <li><strong>extensions.logging.enabled</strong> = <strong>true</strong>. This will send more detailed information about installation and update problems to the Error Console.</li>
+</ul>
+<h2 id=".E5.BC.80.E5.8F.91.E6.89.A9.E5.B1.95" name=".E5.BC.80.E5.8F.91.E6.89.A9.E5.B1.95">开发扩展</h2>
+<p>这些扩展可以帮组你进行扩展开发.</p>
+<ul>
+ <li>DOM 检查器, 自定义安装的一个选项.</li>
+ <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/216">Venkman</a>, 一个JavaScript 调试器.</li>
+ <li><a class="link-https" href="https://addons.mozilla.org/en-US/firefox/addon/7434/">扩展开发者的扩展</a></li>
+ <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/1815">Console<sup>2</sup></a></li>
+ <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/4453">Chrome 清单</a></li>
+ <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/1843">Firebug</a></li>
+ <li><a class="link-https" href="https://addons.mozilla.org/firefox/addon/1729">Execute JS</a></li>
+ <li><a class="external" href="http://xpcomviewer.mozdev.org">XPCOMViewer</a>, 一个XPCOM 检查器</li>
+</ul>
+<h2 id=".E8.87.AA.E5.AE.9A.E4.B9.89.E4.BB.A3.E7.A0.81.E4.BD.8D.E7.BD.AE" name=".E8.87.AA.E5.AE.9A.E4.B9.89.E4.BB.A3.E7.A0.81.E4.BD.8D.E7.BD.AE">扩展开发目录设定</h2>
+<p>每次因遇到某些变更而不得不重新添加扩展部分的时候,以及,为了保护您的"扩展源文件"不受到卸载过程中被意外删除的风险,其实您可以把"扩展插件目录"从"标准用户配置目录"中移出到你自己想要的文件目录中进行开发。具体操作步骤如下:</p>
+<ol>
+ <li>找到扩展ID:从install.rdf中找到你的扩展ID号,install.rdf就安装在扩展插件的根目录中;</li>
+ <li>建立文件:在“用户配置目录/extensions/”目录下,用你的扩展插件ID号作为文件名新建一个文件。 (比如: `用户配置目录/extensions/{46D1B3C0-DB7A-4b1a-863A-6EE6F77ECB58}`) (<a class="external" href="http://kb.mozillazine.org/Profile_folder">找到你的用户配置目录所在位置</a>),记得没有文件扩展名。(为了方便说明暂把这个文件称作“扩展外链定位文件” )</li>
+ <li>设定文件内容:“扩展外链定位文件”里要包含一个路径,这个路径是指向扩展程序的install.rdf所在目录的路径。(例如:`/full/path/to/yourExtension`. Windows用户注意,用大写书写驱动器名以及反斜杠而不是正斜杠,比如:`C:\full\path\to\yourExtension` Here is an example 'C:\sam\workspace\toolbar\helloWorldtoolbar\'). 在Firefox3中, 如果你是通过XPI包安装的扩展,`用户配置目录`下部分或者所有extensions.*的文件可能会被重新设置。虽然这些文件系统会自动重新生成的,还是备份一下先。</li>
+ <li>把“扩展外链定位文件”放在你的用户配置目录中的扩展目录(`用户配置目录/extension`)下,重启Firefox。</li>
+</ol>
+<h2 id=".E4.BD.BF.E7.94.A8.E7.9B.AE.E5.BD.95.E8.80.8C.E9.9D.9EJAR" name=".E4.BD.BF.E7.94.A8.E7.9B.AE.E5.BD.95.E8.80.8C.E9.9D.9EJAR">使用目录而非JAR</h2>
+<p>无论你是否选择将你的扩展 chrome打包成JAR或是目录,在目录下开发会更简单。如果你选择了一个用于分发的JAR,你仍然可以通过编辑chrome.manifest工作在目录形式下。比如下面的例子</p>
+<pre class="eval">content myExtension jar:chrome/myExtension.jar!/content/
+</pre>
+<p>不如</p>
+<pre class="eval">content myExtension chrome/content/
+</pre>
diff --git a/files/zh-cn/mozilla/add-ons/submitting_an_add-on_to_amo/index.html b/files/zh-cn/mozilla/add-ons/submitting_an_add-on_to_amo/index.html
new file mode 100644
index 0000000000..5ffb14d889
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/submitting_an_add-on_to_amo/index.html
@@ -0,0 +1,24 @@
+---
+title: 向AMO提交一个附加组件
+slug: Mozilla/Add-ons/Submitting_an_add-on_to_AMO
+translation_of: Mozilla/Add-ons/Distribution
+---
+<p>当你为基于Mozilla的软件(如Firefox,Thunderbird等)制作出了一个全新的附加组件时,你一定希望其他人能够找,到下载并使用它。</p>
+<p>Mozilla provides the <a class="external" href="http://addons.mozilla.org" rel="freelink">http://addons.mozilla.org</a> (AMO) web site to provide a repository for add-ons for Mozilla software. When users click the "Get Extensions" link in the <strong>Add-ons</strong> window in Firefox, for example, they are directed to this site.</p>
+<p>That makes AMO a great way to get your add-ons to the public. This article provides details on how to submit your article to AMO for distribution.</p>
+<div class="note">
+ <strong>Not</strong><strong>e:</strong> Attaching your add-on to articles on the Mozilla Developer Center web site won't do you a lot of good, as we delete them.  This is not the right place to post your add-ons; please follow the instructions here instead.</div>
+<h2 id="Step_1:_Write_your_add-on" name="Step_1:_Write_your_add-on">第一步:编写你的附加组件</h2>
+<p>This is important. It's hard to get an add-on accepted into AMO if you don't write it first. Really hard.</p>
+<h2 id="Step_2:_Test_your_add-on" name="Step_2:_Test_your_add-on">第二步:测试你的附加组件</h2>
+<p>Make sure it works before you submit it. You should try it out on every product you claim to support. In other words, you don't want to advertise that it works in both Firefox and Thunderbird if you haven't tested it in both. Make sure it works in every version you claim to support, too.</p>
+<h2 id="Step_3:_Package_your_add-on" name="Step_3:_Package_your_add-on">第三步:打包你的附加组件</h2>
+<p>Add-ons distributed by AMO need to be packaged properly as XPI files. See <a href="/en/Extension_Packaging" title="en/Extension_Packaging">Extension Packaging</a> for information on how to do this.</p>
+<h2 id="Step_4:_Get_an_AMO_account" name="Step_4:_Get_an_AMO_account">第四部:注册一个AMO账户</h2>
+<p>You'll need to have an AMO account so that you can make submissions. To get one, visit the <a class="link-https" href="https://addons.mozilla.org/en-US/firefox/users/register">Register</a> link at the top of any page on the AMO website. Fill out the form and follow the instructions to activate your account.</p>
+<p>Obviously, you can skip this step if you already have an AMO account.</p>
+<h2 id="Step_5:_Submit_your_add-on" name="Step_5:_Submit_your_add-on">第五步:提交你的附加组件</h2>
+<p>To submit an add-on, go to the <a class="link-https" href="https://addons.mozilla.org/developers" title="https://addons.mozilla.org/developers">Developer Control Panel</a>.</p>
+<p>You will then be asked to supply a file, as well as information about the add-on.</p>
+<p>Once the add-on has been reviewed, it will be made available for downloading. Reviews can take a varying amount of time depending on how many pending submissions there are and the availability of people to perform the reviews.</p>
+<h2 id="languages(_fr_frSoumettre_un_module_sur_AMO_)">{{ languages( { "fr": "fr/Soumettre_un_module_sur_AMO" } ) }}</h2>
diff --git a/files/zh-cn/mozilla/add-ons/themes/index.html b/files/zh-cn/mozilla/add-ons/themes/index.html
new file mode 100644
index 0000000000..e7c28ba50c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/themes/index.html
@@ -0,0 +1,65 @@
+---
+title: 主题
+slug: Mozilla/Add-ons/Themes
+tags:
+ - Themes
+translation_of: Mozilla/Add-ons/Themes
+---
+<p>
+</p>
+<div class="callout-box"><b><a href="cn/Creating_a_Skin_for_Firefox">Getting Started</a></b><br>
+介绍如何为Firefox开发主题。</div>
+<div><b>主题</b>指的是程序的皮肤,通过它可以改变程序的外观,满足不同人的不同需要。一个主题可以只改变界面的颜色,也可以改变界面相关的所有元素。</div>
+<table class="topicpage-table">
+<tbody><tr>
+<td>
+<h4 id="Documentation" name="Documentation"> <a>Documentation</a> </h4>
+<dl><dt> <a href="cn/%e5%88%9b%e5%bb%ba%e4%b8%80%e5%a5%97_Firefox_%e7%9a%ae%e8%82%a4">创建一套 Firefox 皮肤</a>
+</dt><dd> <small>介绍如何为Firefox创建新的主题。</small>
+</dd></dl>
+<p><span class="comment">一般style翻译成样式</span>
+</p>
+<dl><dt> <a href="cn/%e4%b8%bb%e9%a2%98%e6%89%93%e5%8c%85">主题打包</a>
+</dt><dd> <small>如何将Firefox和Thunderbird的主题打包。</small>
+</dd></dl>
+<dl><dt> <a href="cn/Theme_changes_in_Firefox_3"> Firefox 2.0 和 3.0 间的主题变更</a>
+</dt></dl>
+<dl><dt> <a href="cn/Theme_changes_in_Firefox_2"> Firefox 1.5 和 2.0 间的主题变更</a>
+</dt><dd> <small> Firefox 发行版1.5和2.0之间的主题全部变更清单。</small>
+</dd></dl>
+<dl><dt> <a class="external" href="http://forums.mozillazine.org/viewtopic.php?t=197434">Firefox 1.5 和 2.0 间的主题变更 (forum post)</a>
+</dt><dd> <small>A forum post at <a class="external" href="http://www.mozillazine.org">MozillaZine</a> outlining the basic theme-related changes between Firefox 1.0 and 1.5.</small>
+</dd></dl>
+<dl><dt> <a class="external" href="http://cheeaun.phoenity.com/weblog/2004/12/first-steps-in-theme-design.html">主题设计的第一步</a>
+</dt><dd> <small>A somewhat aged article discussing theme design for Firefox.</small>
+</dd></dl>
+<p><span class="alllinks"><a>View All...</a></span>
+</p>
+</td><td>
+<h4 id="Community" name="Community"> Community </h4>
+<ul><li> View Mozilla forums...
+</li></ul>
+<p>{{ DiscussionList("dev-themes", "mozilla.dev.themes") }}
+</p>
+<ul><li> <a class="link-irc" href="irc://irc.mozilla.org/#themedev">#themedev IRC channel</a>
+</li><li> <a class="external" href="http://forums.mozillazine.org/viewforum.php?f=18">MozillaZine Themes forum</a>
+</li></ul>
+<h4 id="Tools" name="Tools"> Tools </h4>
+<ul><li> <a href="cn/DOM_Inspector">DOM Inspector</a>
+</li><li> <a class="link-https" href="https://addons.mozilla.org/firefox/63/">InspectorWidget</a>
+</li><li> <a class="external" href="http://www.extensionsmirror.nl/index.php?showtopic=21">ChromeEdit extension</a>
+</li></ul>
+<p><span class="alllinks"><a>View All...</a></span>
+</p>
+<h4 id="Related_Topics" name="Related_Topics"> Related Topics </h4>
+<dl><dd> <a href="cn/CSS">CSS</a>
+</dd></dl>
+</td></tr></tbody></table>
+<p><span class="comment">Categories</span>
+</p><p><span class="comment">Interwiki Language Links</span>
+</p><p><br>
+</p><p><br>
+</p>
+<div class="noinclude">
+</div>
+{{ languages( { "de": "de/Themes", "en": "en/Themes", "es": "es/Temas", "fr": "fr/Th\u00e8mes", "ja": "ja/Themes", "pl": "pl/Motywy", "zh-tw": "zh_tw/\u4f48\u666f\u4e3b\u984c" } ) }}
diff --git a/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/index.html b/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/index.html
new file mode 100644
index 0000000000..2301b757e7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/index.html
@@ -0,0 +1,28 @@
+---
+title: 创建一套_Firefox_皮肤
+slug: Mozilla/Add-ons/Themes/Obsolete/Creating_a_Skin_for_Firefox
+tags:
+ - Themes
+translation_of: Archive/Themes/Creating_a_Skin_for_Firefox
+---
+<p> </p>
+<h3 id=".E8.AF.B4.E6.98.8E" name=".E8.AF.B4.E6.98.8E">说明</h3>
+<p>为了为 Firefox 创建一套皮肤, 你必须知道三件事:如何编辑图像、如何释放zip文件、以及如何更改CSS。Firefox 的按钮图标使用标准的gif、png、和 jpeg 图像并使用 CSS 来定义界面上的一切。</p>
+<p><b>什么是皮肤?</b></p>
+<p>皮肤不会改版总体的界面;相反的,它仅仅定义了界面看上去的样子。你无法改版用户右击一个图像时发生什么事情,但你可以改版右键菜单的外观(例如使其变为带有粉色圆点装饰)。如果你想更改Firefox的功能,你不得不去改变chrome,这不在本文讨论的范围之内。</p>
+<h3 id=".E5.86.85.E5.AE.B9" name=".E5.86.85.E5.AE.B9">内容</h3>
+<ul>
+ <li><a href="cn/%e5%88%9b%e5%bb%ba%e4%b8%80%e5%a5%97Firefox%e7%9a%ae%e8%82%a4/%e4%bb%8e%e8%bf%99%e9%87%8c%e5%bc%80%e5%a7%8b">从这里开始</a></li>
+</ul>
+<div class="originaldocinfo">
+ <h3 id=".E6.96.87.E7.AB.A0.E5.8E.9F.E5.A7.8B.E4.BF.A1.E6.81.AF" name=".E6.96.87.E7.AB.A0.E5.8E.9F.E5.A7.8B.E4.BF.A1.E6.81.AF">文章原始信息</h3>
+ <ul>
+ <li>作者:Neil Marshall 和 Tucker Lee</li>
+ <li>其它贡献者 (建议/校正):Brent Marshall, CDN (<a class="external" href="http://themes.mozdev.org" rel="freelink">http://themes.mozdev.org</a>), JP Martin, Boris Zbarsky, Asa Dotzler, WeSaySo, David James, Dan Mauch, Anders Conbere, Tim Regula (<a class="external" href="http://www.igraphics.nn.cx" rel="freelink">http://www.igraphics.nn.cx</a>)</li>
+ <li>版权信息:Copyright 2002-2003 Neil Marshall, permission given to MDC to migrate into the wiki April 2005 via email.</li>
+ <li>原始链接:<a class="external" href="http://www.eightlines.com/neil/mozskin" rel="freelink">http://www.eightlines.com/neil/mozskin</a></li>
+ </ul>
+</div>
+<div class="noinclude">
+  </div>
+<p>{{ languages( { "de": "de/Theme_erstellen", "es": "es/Creando_un_tema_para_Firefox", "fr": "fr/Cr\u00e9er_un_th\u00e8me_pour_Firefox", "ja": "ja/Creating_a_Skin_for_Firefox", "pl": "pl/Tworzenie_sk\u00f3rek_dla_Firefoksa" } ) }}</p>
diff --git a/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/uuid/index.html b/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/uuid/index.html
new file mode 100644
index 0000000000..37280321a1
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/themes/obsolete/creating_a_skin_for_firefox/uuid/index.html
@@ -0,0 +1,6 @@
+---
+title: 创建一套Firefox皮肤
+slug: Mozilla/Add-ons/Themes/Obsolete/Creating_a_Skin_for_Firefox/UUID
+translation_of: Archive/Themes/Creating_a_Skin_for_Firefox/UUID
+---
+<p>{{wiki.localize('System.API.page-generated-for-subpage')}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/themes/obsolete/index.html b/files/zh-cn/mozilla/add-ons/themes/obsolete/index.html
new file mode 100644
index 0000000000..d420b6ebf0
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/themes/obsolete/index.html
@@ -0,0 +1,10 @@
+---
+title: Obsolete
+slug: Mozilla/Add-ons/Themes/Obsolete
+tags:
+ - NeedsTranslation
+ - TopicStub
+translation_of: Mozilla/Add-ons/Themes/Obsolete
+---
+<p>This page collects theme docs that we don't expect will ever be updated, but which we're keeping for the time being as potential source material for updated docs.</p>
+<p>{{ ListSubPages ("/en-US/Add-ons/Themes/Obsolete", 5) }}</p>
diff --git a/files/zh-cn/mozilla/add-ons/themes/obsolete/theme_changes_in_firefox_3/index.html b/files/zh-cn/mozilla/add-ons/themes/obsolete/theme_changes_in_firefox_3/index.html
new file mode 100644
index 0000000000..595058f253
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/themes/obsolete/theme_changes_in_firefox_3/index.html
@@ -0,0 +1,92 @@
+---
+title: Firefox 3 的界面改动
+slug: Mozilla/Add-ons/Themes/Obsolete/Theme_changes_in_Firefox_3
+tags:
+ - Themes
+translation_of: Archive/Themes/Theme_changes_in_Firefox_3
+---
+<p>{{ Fx_minversion_header(3) }} {{ Draft() }}</p>
+<p>本文包含了更新FireFox主题以使其可以在<a href="cn/Firefox_3">Firefox 3</a>下良好表现所需进行的一些改动。</p>
+<div class="note">
+ <b>Note:</b> We could use an article called <a href="cn/Updating_themes_for_Firefox_3">Updating themes for Firefox 3</a> that would serve as a how-to guide for updating themes. If anyone with theming experience would like to write one, please do!</div>
+<h2 id=".E9.BB.98.E8.AE.A4.E4.B8.BB.E9.A2.98.E7.9A.84.E6.94.B9.E5.8A.A8" name=".E9.BB.98.E8.AE.A4.E4.B8.BB.E9.A2.98.E7.9A.84.E6.94.B9.E5.8A.A8">默认主题的改动</h2>
+<p>下表列出了Firefox 3默认主题的一些改动。你可以对照此表,确认你所需要做出的改动。</p>
+<h3 id=".E6.89.80.E6.9C.89.E6.96.87.E4.BB.B6" name=".E6.89.80.E6.9C.89.E6.96.87.E4.BB.B6">所有文件</h3>
+<h4 id=".E6.89.80.E6.9C.89.E5.B9.B3.E5.8F.B0" name=".E6.89.80.E6.9C.89.E5.B9.B3.E5.8F.B0">所有平台</h4>
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td class="header">文件</td>
+ <td class="header">变更</td>
+ </tr>
+ <tr>
+ <td>&lt;tt&gt;browser/themes/*/browser/browser.css&lt;/tt&gt;</td>
+ <td>The width of the drag and drop indicator is no longer calculated during the drag (tabbrowser.xml). Instead a '-moz-margin-start' property must be added to .tab-drop-indicator-bar, with a value that is half of the width of the indicator image. Also, the visibility of the indicator is now controlled by setting collapsed in tabbrowser.xml. As a result, the 'display' property should be removed from .tab-drop-indicator-bar (including for dragging="true").</td>
+ </tr>
+ </tbody>
+</table>
+<h4 id="Mac_OS_X" name="Mac_OS_X">Mac OS X</h4>
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td class="header">文件</td>
+ <td class="header">变动信息</td>
+ </tr>
+ <tr>
+ <td>&lt;tt&gt;browser/themes/pinstripe/browser/tabbrowser/tabDragIndicator.png&lt;/tt&gt;</td>
+ <td>删除了图片边缘多余的空白,现在图片尺寸变小。也许会对其他使用此图片的Mac平台下的主题产生影响。</td>
+ </tr>
+ <tr>
+ <td>&lt;tt&gt;browser/themes/pinstripe/browser/browser.css&lt;/tt&gt;</td>
+ <td>.tabbrowser-tab{{ mediawiki.external('first-tab=\"true\"') }} &gt; .tab-image-left不再具有margin-left属性,现在使用定义了相同宽度的.tabs-left元素来替代。在FireFox 2的默认皮肤Winstripe中已经作此处理。</td>
+ </tr>
+ </tbody>
+</table>
+<h3 id="browser.E7.9A.84.E6.94.B9.E5.8A.A8" name="browser.E7.9A.84.E6.94.B9.E5.8A.A8">&lt;tt&gt;browser&lt;/tt&gt;的改动</h3>
+<h3 id="global.E7.9A.84.E6.94.B9.E5.8A.A8" name="global.E7.9A.84.E6.94.B9.E5.8A.A8">&lt;tt&gt;global&lt;/tt&gt;的改动</h3>
+<h4 id=".E6.89.80.E6.9C.89.E5.B9.B3.E5.8F.B0_2" name=".E6.89.80.E6.9C.89.E5.B9.B3.E5.8F.B0_2">所有平台</h4>
+<p>“跳转到”按钮现在被放置在地址栏内部,所以此按钮所用的图片(&lt;tt&gt;<a class="external" rel="freelink">chrome://browser/skin/Go-arrow.png</a>&lt;/tt&gt;)需要设计的小一些。控制“跳转到”及其他地址栏中所用到的按钮的显示及隐藏的CSS规则为:</p>
+<pre class="eval">#urlbar[pageproxystate="invalid"] &gt; #urlbar-icons &gt; :not(#go-button) ,
+#urlbar[pageproxystate="valid"] &gt; #urlbar-icons &gt; #go-button {
+ visibility: collapse;
+}
+</pre>
+<h5 id=".E5.A2.9E.E5.8A.A0.E7.9A.84.E5.9B.BE.E7.89.87" name=".E5.A2.9E.E5.8A.A0.E7.9A.84.E5.9B.BE.E7.89.87">增加的图片</h5>
+<p>增加了以下图片:</p>
+<dl>
+ <dt>
+ &lt;tt&gt;<a class="external" rel="freelink">chrome://global/skin/icons/information-16.png</a>&lt;/tt&gt;</dt>
+ <dd>
+ Used when presenting information notices。</dd>
+ <dt>
+ &lt;tt&gt;<a class="external" rel="freelink">chrome://global/skin/icons/warning-16.png</a>&lt;/tt&gt;</dt>
+ <dd>
+ 用作显示警告窗口。</dd>
+</dl>
+<h5 id=".E7.A7.BB.E9.99.A4.E7.9A.84.E5.9B.BE.E7.89.87" name=".E7.A7.BB.E9.99.A4.E7.9A.84.E5.9B.BE.E7.89.87">移除的图片</h5>
+<p>以下图片被移除:</p>
+<dl>
+ <dt>
+ &lt;tt&gt;<a class="external" rel="freelink">chrome://mozapps/skin/extensions/question.png</a>&lt;/tt&gt;</dt>
+ <dd>
+ 不再使用。</dd>
+</dl>
+<h4 id="Mac_OS_X_2" name="Mac_OS_X_2">Mac OS X</h4>
+<p>为Mac OS X平台上的Firefox 3制作的皮肤需要在&lt;tt&gt;<a class="external" rel="freelink">chrome://global/skin/wizard.css</a>&lt;/tt&gt;末尾增加两条CSS规则:</p>
+<pre class="eval">.wizard-buttons-btm {
+ padding:<i>X</i>px;
+}
+
+.wizard-label-box {
+ display: none;
+}
+</pre>
+<p>此处的数字
+ <i>
+ X</i>
+ ,即&lt;tt&gt;.wizard-buttons-btm&lt;/tt&gt;中的padding值,需要和&lt;tt&gt;.wizard-buttons-box-2&lt;/tt&gt;中的margin值相同。</p>
+<h5 id=".E5.9B.BE.E7.89.87.E5.8F.98.E5.8A.A8" name=".E5.9B.BE.E7.89.87.E5.8F.98.E5.8A.A8">图片变动</h5>
+<p><a class="external" rel="freelink">chrome://global/skin/icons/loading_16.gif</a> 被chrome://global/skin/icons/loading_16.png 替代。</p>
+<h3 id="mozapps.E7.9A.84.E6.94.B9.E5.8A.A8" name="mozapps.E7.9A.84.E6.94.B9.E5.8A.A8">&lt;tt&gt;mozapps&lt;/tt&gt;的改动</h3>
+<h2 id=".E5.8F.82.E8.80.83.E6.96.87.E7.AB.A0" name=".E5.8F.82.E8.80.83.E6.96.87.E7.AB.A0">参考文章</h2>
+<p><a href="cn/Theme_changes_in_Firefox_2">Theme changes in Firefox 2</a></p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/add_a_button_to_the_toolbar/index.html b/files/zh-cn/mozilla/add-ons/webextensions/add_a_button_to_the_toolbar/index.html
new file mode 100644
index 0000000000..64ec49a146
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/add_a_button_to_the_toolbar/index.html
@@ -0,0 +1,220 @@
+---
+title: Add a button to the toolbar
+slug: Mozilla/Add-ons/WebExtensions/Add_a_button_to_the_toolbar
+translation_of: Mozilla/Add-ons/WebExtensions/Add_a_button_to_the_toolbar
+---
+<div>{{AddonSidebar}}</div>
+
+<div>工具栏按钮是webextensions的一种主要UI组件,它在浏览器的工具栏中作为图标显示。当用户点击图标时,就会发生下面两种事件中的一样:</div>
+
+<ul>
+ <li>如果按钮有弹出菜单,则显示该弹出。 弹出菜单是一个临时对话,它必须使用HTML,CSS,JavaScript语言表示。</li>
+ <li>如果没有弹出菜单, 则生成一个单击事件, 你可以在代码中监听该事件并执行其他响应。</li>
+</ul>
+
+<p>在WebExtensions中这种按钮被称为浏览器行为按钮,它们可以像下面这样生成:</p>
+
+<ul>
+ <li>manifest.json 文件中的键 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code> 被用来定义按钮。</li>
+ <li>JavaScript 接口 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction">browserAction</a></code> 被用来监听单击和更改按钮,或通过代码执行操作。</li>
+</ul>
+
+<h2 id="一个简单的按钮">一个简单的按钮</h2>
+
+<p>在这一节中我们将创建一个工具栏按钮的 WebExtension 。当用户单击按钮时,会打开一个<a href="https://developer.mozilla.org">https://developer.mozilla.org</a> 的新标签页.</p>
+
+<p>首先,新建名为 "button"的文件夹, 在该文件夹下创建名为"manifest.json" 的文件,内容如下:</p>
+
+<pre class="brush: json">{
+
+ "description": "Demonstrating toolbar buttons",
+ "manifest_version": 2,
+ "name": "button-demo",
+ "version": "1.0",
+
+ "background": {
+ "scripts": ["background.js"]
+ },
+
+ "browser_action": {
+ "default_icon": {
+ "16": "icons/page-16.png",
+ "32": "icons/page-32.png"
+ }
+ }
+
+}</pre>
+
+<p>上面内容显示有一个名为“ background .js ”后台脚本,以及在“ icons ”文件夹下的浏览器行为按钮图标。</p>
+
+<div class="pull-aside">
+<div class="moreinfo">These icons are from the <a href="https://www.iconfinder.com/iconsets/bitsies">bitsies!</a> iconset created by Recep Kütük.</div>
+</div>
+
+<p>接下来,在"buttons" 文件夹下创建 "icons" 文件夹,在该文件夹下存放下面的图标文件 :</p>
+
+<ul>
+ <li>"page-16.png" (<img alt="" src="https://mdn.mozillademos.org/files/13476/page-16.png" style="height: 16px; width: 16px;">)</li>
+ <li>"page-32.png" (<img alt="" src="https://mdn.mozillademos.org/files/13478/page-32.png" style="height: 32px; width: 32px;">).</li>
+</ul>
+
+<div style=""> </div>
+
+<p>我们有两个图标,大图标用于在高分辨率状态下显示。浏览器会自动选择合适的图标。</p>
+
+<p>接着,在附加组件的根目录下创建 "background.js"文件 , 内容如下:</p>
+
+<pre class="brush: js">function openPage() {
+ browser.tabs.create({
+ url: "https://developer.mozilla.org"
+ });
+}
+
+browser.browserAction.onClicked.addListener(openPage);</pre>
+
+<p>该文件用来监听浏览器单击事件。当单击事件发生时运行 <code>openPage()</code> 函数,这个函数通过使用<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs">tabs</a></code> 接口加载指定的页面。</p>
+
+<p>现在完整的附加组件看上去应该像下面这样:</p>
+
+<pre class="line-numbers language-html"><code class="language-html">button/
+ icons/
+ page-16.png
+ page-32.png
+ background.js
+ manifest.json</code></pre>
+
+<p>安装这个<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">WebExtension</a> ,然后单击按钮:</p>
+
+<p>{{EmbedYouTube("kwwTowgT-Ys")}}</p>
+
+<h2 id="添加一个弹出菜单">添加一个弹出菜单</h2>
+
+<p>尝试在按钮上添加一个弹出菜单。 修改 "manifest.json"如下:</p>
+
+<pre class="brush: json">{
+
+ "description": "Demonstrating toolbar buttons",
+ "manifest_version": 2,
+ "name": "button-demo",
+ "version": "1.0",
+
+ "browser_action": {
+ "browser_style": true,
+ "default_popup": "popup/choose_page.html",
+ "default_icon": {
+ "16": "icons/page-16.png",
+ "32": "icons/page-32.png"
+ }
+ }
+
+}</pre>
+
+<p>我们把原文件做了三处改变:</p>
+
+<ul>
+ <li>我们不需要引用“ background.js ”文件,因为会在弹出菜单的脚本中处理该行为 (你也可以使用“background.js“来运行一个弹出窗口,只是现在我们不需要这么做).</li>
+ <li>我们添加了<code>"browser_style": true</code>, 使弹出样式看上去更像是浏览器的一部分。</li>
+ <li>最后,我们添加 <code>"default_popup": "popup/choose_page.html"</code>, 告诉浏览器按钮被单击时弹出菜单,菜单的内容则在"popup/choose_page.html"页面中.</li>
+</ul>
+
+<p>现在我们要创建弹出菜单。新建名为 "popup" 的文件夹,然后在文件夹内创建"choose_page.html" 文件,该文件内容如下:</p>
+
+<pre class="brush: html">&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;meta charset="utf-8"&gt;
+ &lt;link rel="stylesheet" href="choose_page.css"/&gt;
+ &lt;/head&gt;
+
+&lt;body&gt;
+ &lt;div class="page-choice"&gt;developer.mozilla.org&lt;/div&gt;
+ &lt;div class="page-choice"&gt;support.mozilla.org&lt;/div&gt;
+ &lt;div class="page-choice"&gt;addons.mozilla.org&lt;/div&gt;
+ &lt;script src="choose_page.js"&gt;&lt;/script&gt;
+&lt;/body&gt;
+
+&lt;/html&gt;</pre>
+
+<p>你会发现这是一个普通的HTML页面,它包含三个 {{htmlelement("div")}}元素,在每个元素中有一个Mozilla页面地址。另外还包括一个 CSS文件和一个JavaScript文件,我们会在后面添加它们。</p>
+
+<p>在 "popup" 文件夹下,创建名为 "choose_page.css" 的文件,内容如下:</p>
+
+<pre class="brush: css">html, body {
+ width: 300px;
+}
+
+.page-choice {
+ width: 100%;
+ padding: 4px;
+ font-size: 1.5em;
+ text-align: center;
+ cursor: pointer;
+}
+
+.page-choice:hover {
+ background-color: #CFF2F2;
+}</pre>
+
+<p>这是我们弹出菜单的部分样式。</p>
+
+<p>接着,在 "popup" 文件夹下,创建名为 "choose_page.js" 的文件,内容如下:</p>
+
+<pre class="brush: js">document.addEventListener("click", function(e) {
+ if (!e.target.classList.contains("page-choice")) {
+ return;
+ }
+
+ var chosenPage = "https://" + e.target.textContent;
+ browser.tabs.create({
+ url: chosenPage
+ });
+
+});</pre>
+
+<p>在我们的脚本中,我们会监听单击的弹出项。首先检查单击的对象是否在给出的页面选择项中,如果不在,则不做任何处理;如果在,则从单击的页面选择项中获取URL地址,然后打开一个对应页面的新标签页。注意:我们在弹出脚本中使用WebExtension接口,和在后台脚本中使用接口一样。</p>
+
+<p>附加组件的结构最后看上去应该像下面这样:</p>
+
+<pre>button/
+ icons/
+ page-16.png
+ page-32.png
+ popup/
+ choose_page.css
+ choose_page.html
+ choose_page.js
+ manifest.json</pre>
+
+<p>重新加载附加组件,再次单击按钮,并尝试在弹出菜单中单击某个选择项:</p>
+
+<p>{{EmbedYouTube("QPEh1L1xq0Y")}}</p>
+
+<h2 id="页面行为">页面行为</h2>
+
+<p>页面行为<a href="/en-US/Add-ons/WebExtensions/User_interface_components#Page_actions">(Page actions)</a> 类似浏览器行为,只是页面行为仅针对特定页面,而浏览器行为则全局有效。</p>
+
+<p>由于浏览器行为总是发生,而页面行为只在特定页面显示。所以页面行为按钮在URL地址栏中显示,而浏览器行为按钮则在浏览器工具栏中显示。</p>
+
+<h2 id="了解更多">了解更多</h2>
+
+<ul>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code> manifest key</li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction">browserAction</a></code> API</li>
+ <li>Browser action examples:
+ <ul>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/beastify">beastify</a></li>
+ <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/bookmark-it">Bookmark it!</a></li>
+ <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/favourite-colour">favourite-colour</a></li>
+ <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/inpage-toolbar-ui">inpage-toolbar-ui</a></li>
+ <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/open-my-page-button">open-my-page-button</a></li>
+ </ul>
+ </li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/page_action">page_action</a></code> manifest key</li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/pageAction">pageAction</a></code> API</li>
+ <li>Page action examples:
+ <ul>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/chill-out">chill-out</a></li>
+ </ul>
+ </li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/anatomy_of_a_webextension/index.html b/files/zh-cn/mozilla/add-ons/webextensions/anatomy_of_a_webextension/index.html
new file mode 100644
index 0000000000..a405ac2f87
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/anatomy_of_a_webextension/index.html
@@ -0,0 +1,148 @@
+---
+title: 剖析拓展
+slug: Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension
+tags:
+ - WebExtension
+ - 拓展
+ - 拓展开发
+translation_of: Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension
+---
+<div>{{AddonSidebar}}</div>
+
+<p>拓展是指一个包含若干文件的安装包,可直接分发至用户。本文中,我们快速地介绍一遍安装包内可能出现的文件。</p>
+
+<h2 id="manifest.json">manifest.json</h2>
+
+<p>这是唯一一个在每个 WebExtension 里面必须存在的文件。它包含了关于这个扩展插件基本的元数据(metadata),比如它的名字、版本和所需权限。并且,它也对 WebExtension 中其他文件进行了链接。</p>
+
+<p>这个 manifest 文件还可以指向其它一些类型的文件:</p>
+
+<ul>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts">background pages</a>: 执行一个长时间运行的逻辑</li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Content_scripts">content scripts</a>: 与网页进行交互(注意:这与JavaScript在页面中的 {{HTMLElement("script")}} 元素不一样)</li>
+ <li><a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Browser_actions_2">browser action files</a>: 在工具栏中添加按钮</li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Page_actions">page action files</a>: 在地址栏添加按钮</li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Options_pages">options pages</a>: 为用户定义一个可浏览的UI界面,可以改变插件的设置</li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Web_accessible_resources">web-accessible resources</a>: 使打包好的内容可用于网页与目录脚本</li>
+</ul>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/12954/webextension-anatomy.svg" style="display: block; height: 581px; margin-left: auto; margin-right: auto; width: 600px;"></p>
+
+<p>浏览其他的详细信息请到 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> 。</p>
+
+<p>除了这些 manifest 引用的文件之外,扩展也可以携带额外的 <a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Extension_pages">Extension pages</a> 。</p>
+
+<h2 id="后台脚本">后台脚本</h2>
+
+<p>扩展常常需要独立于任何浏览器窗口或特定网页来维持一种长期的状态或者执行长期的操作。这就是后台脚本(background scripts)的职责。</p>
+
+<p>后台脚本将在拓展加载完毕后开始运行,直到拓展被禁用或卸载。只要获得了相应的<a href="/zh-CN/Add-ons/WebExtensions/manifest.json/permissions">权限</a>,你就可以在脚本中使用任何 <a href="/zh-CN/Add-ons/WebExtensions/API">WebExtension API</a>。</p>
+
+<h3 id="指定后台脚本">指定后台脚本</h3>
+
+<p>你可以通过在 manifest.json 中添加关键字 <code>background</code> 来引入后台脚本:</p>
+
+<pre class="brush: json">// manifest.json
+
+"background": {
+ "scripts": ["background-script.js"]
+}</pre>
+
+<p>可以添加多份后台脚本:而且,就像同一个网页中的多个脚本一样,它们将会运行在同一上下文环境中。</p>
+
+<p> </p>
+
+<p>与此同时,你也可以先引入一个后台页面,再在后台页面中引入脚本。这样做能为后台脚本添加 ES 6 模块支持,算是一个优势。</p>
+
+<p style="margin-bottom: 0em;"><strong>manifest.json</strong></p>
+
+<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="comment token">// manifest.json</span>
+
+<span class="key token">"background":</span> <span class="punctuation token">{</span>
+ <span class="key token">"page":</span> <span class="string token">"background-page.html"</span>
+<span class="punctuation token">}</span></code></pre>
+
+<p style="margin-bottom: 0em;"><strong>background-page.html</strong></p>
+
+<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="doctype token">&lt;!DOCTYPE html&gt;</span>
+<span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>html</span> <span class="attr-name token">lang</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"zh-CN</span><span class="punctuation token">"</span></span><span class="punctuation token">&gt;</span></span>
+ <span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>head</span><span class="punctuation token">&gt;</span></span>
+ <span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>meta</span> <span class="attr-name token">charset</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>utf-8<span class="punctuation token">"</span></span><span class="punctuation token">&gt;</span></span>
+ <span class="tag token"><span class="tag token"><span class="punctuation token">&lt;</span>script</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>module<span class="punctuation token">"</span></span> <span class="attr-name token">src</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>background-script.js<span class="punctuation token">"</span></span><span class="punctuation token">&gt;</span></span><span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>script</span><span class="punctuation token">&gt;</span></span>
+ <span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>head</span><span class="punctuation token">&gt;</span></span>
+<span class="tag token"><span class="tag token"><span class="punctuation token">&lt;/</span>html</span><span class="punctuation token">&gt;</span></span></code></pre>
+
+<p> </p>
+
+<h3 id="后台脚本的运行环境">后台脚本的运行环境</h3>
+
+<h4 id="DOM_API">DOM API</h4>
+
+<p>后台脚本在一个被称为后台页面的特殊页面的上下文环境中运行。此环境为其提供了全局变量 <code><a href="/zh-CN/docs/Web/API/Window">window</a></code> ,也提供了所有的标准 DOM API。</p>
+
+<h4 id="WebExtension_API">WebExtension API</h4>
+
+<p>只要扩展获得了必要的<a href="/zh-CN/Add-ons/WebExtensions/manifest.json/permissions">权限</a>,后台脚本就可以使用所有的 <a href="/zh-CN/Add-ons/WebExtensions/API">WebExtension API</a>。</p>
+
+<h4 id="跨域访问">跨域访问</h4>
+
+<p>后台脚本可以向任何拥有<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#%E4%B8%BB%E6%9C%BA%E6%9D%83%E9%99%90">主机权限</a>的主机发送 XHR 请求。</p>
+
+<h4 id="网页内容">网页内容</h4>
+
+<p>后台脚本没有直接访问页面的权限。不过,他们可以在页面中加载<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">内容脚本</a>(content scripts),并且可以<a href="/zh-CN/Add-ons/WebExtensions/Content_scripts#Communicating_with_background_scripts">通过 message-passing API 与内容脚本通信</a>。</p>
+
+<h4 id="内容安全策略">内容安全策略</h4>
+
+<p>根据一个内容安全策略(Content Security Policy),后台脚本不能执行一些可能有危险的操作,例如使用 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval">eval()</a></code>。 详情请参考<a href="/zh-CN/Add-ons/WebExtensions/Content_Security_Policy">内容安全策略</a>。</p>
+
+<h2 id="侧边栏,弹出窗口,选项页面">侧边栏,弹出窗口,选项页面</h2>
+
+<p>您的扩展程序可以包含各种用户界面组件,其内容通过 HTML 文件来定义:</p>
+
+<ul>
+ <li><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Sidebars">侧边栏</a>是一个窗格,它被显示在浏览器窗口左侧,就在网页旁边</li>
+ <li><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Popups">弹出窗口</a>是一个对话框,可以在用户单击<a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Browser_action">工具栏按钮</a>或<a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Page_actions">地址栏按钮</a>时显示该对话框</li>
+ <li><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Options_pages">选项页面</a>是当用户访问拓展在拓展管理器内置的拓展选项页面时内嵌显示的页面。</li>
+</ul>
+
+<p>对于这些组件,你可以创建一个 HTML 文件,并使用 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> 中的特定属性指向它。HTML 文件可以引用 CSS 和 JavaScript 文件,就像普通的网页一样。</p>
+
+<p>所有这些都是<a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Extension_pages">扩展页面</a>的一种,与普通网页不同的是,你可以在其 JavaScript 中使用所有有权限使用的 WebExtension API。 它们甚至可以通过 {{WebExtAPIRef("runtime.getBackgroundPage()")}} 直接访问后台页面中的变量。</p>
+
+<h2 id="扩展页面">扩展页面</h2>
+
+<p>您也可以在扩展中包含HTML文档,这些文档不附加到某个预定义的用户界面组件。与您可能为侧边栏,弹出窗口或选项页面提供的文档不同,它们在manifest.json中没有条目。但是,他们也可以访问所有与您的后台脚本相同的特权WebExtension API。</p>
+
+<p>你通常可以使用 {{WebExtAPIRef("windows.create()")}} 或 {{WebExtAPIRef("tabs.create()")}}加载一个页面.</p>
+
+<p>若想了解更多,请参考 <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Extension_pages">扩展页面</a>。</p>
+
+<h2 id="内容脚本">内容脚本</h2>
+
+<p>一般使用内容脚本来访问和操作页面。内容脚本会被加载到页面中并运行在页面的特定环境下。</p>
+
+<p>内容脚本是由扩展提供的脚本,与页面本身的脚本以及 {{HTMLElement("script")}} 标签中的脚本是不同的。</p>
+
+<p>内容脚本可以像普通脚本一样获取、操作页面的 DOM。</p>
+
+<p>与普通的页面内脚本不同,Content scripts可以:</p>
+
+<ul>
+ <li>执行跨域访问</li>
+ <li>使用 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/API">WebExtension APIs </a>的子集</li>
+ <li>通过与后台脚本交换信息的方式,间接地使用所有<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/API">WebExtension APIs </a></li>
+</ul>
+
+<p>内容脚本无法直接访问普通网页中的脚本,但是可以通过 <code><a href="/zh-CN/docs/Web/API/Window/postMessage">window.postMessage()</a></code> API 来与之传递信息。</p>
+
+<p>通常情况下,当我们讨论内容脚本时,是在指(一类)使用 JavaScript 编写的脚本,但是你也可以用同样的机制来注入 CSS 文件。(译者注:不讨论含有编译器的情况。例如,若你事先引入了可编译 TypeScript 的 JavaScript 内容脚本,不论性能问题,你也很可能可以引入使用 TypeScript 编写的内容脚本:类似这样的情况,在此不计。)</p>
+
+<p>若想了解更多,请参考<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">内容脚本</a>。</p>
+
+<h2 id="Web_accessible_resources">Web accessible resources</h2>
+
+<p>Web accessible resources 是指像图片、HTML、CSS 和 JavaScript 之类的、被引入插件并且想要获得访问权限的内容脚本和页面脚本。这些 web-accessible 的资源可以在页面脚本和内容脚本中通过使用特定的URL方案来引用。<br>
+ 举个例子来说,如果一个内容脚本想要把一些图片插入网页,你可以在插件中引入它们并且使他们成为web-accseeible。接下来内容脚本就可以创建并追加包含 <code>src</code> 属性的 <a href="/zh-CN/docs/Web/HTML/Element/img">img</a> 标签了。</p>
+
+<p>若想了解更多,请参考 manifest.json key 的文档:<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/web_accessible_resources">web_accessible_resources</a>。</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/alarms/create/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/alarms/create/index.html
new file mode 100644
index 0000000000..ac3bafecc4
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/alarms/create/index.html
@@ -0,0 +1,127 @@
+---
+title: alarms.create()
+slug: Mozilla/Add-ons/WebExtensions/API/alarms/create
+tags:
+ - API
+ - WebExtensions
+ - alarms
+ - 创建
+ - 参考
+ - 拓展
+ - 方法
+ - 附件
+ - 非标准
+translation_of: Mozilla/Add-ons/WebExtensions/API/alarms/create
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>创建一个新的alarm.</p>
+
+<h2 id="使用语法">使用语法</h2>
+
+<pre class="syntaxbox brush:js">browser.alarms.create(
+ name, // 可选的字符串(string)类型
+ alarmInfo // 可选的对象(object)类型
+)
+</pre>
+
+<h3 id="参数介绍">参数介绍</h3>
+
+<dl>
+ <dt><code>name</code>{{optional_inline}}</dt>
+ <dd><code>字符串(string)类型。</code>alarm的名称。默认为空的字符串。</dd>
+ <dd>alarm的名称可以在{{WebExtAPIRef('alarms.get()')}}方法和{{WebExtAPIRef('alarms.clear()')}}方法中引用。同时它也可以通过{{WebExtAPIRef('alarms.onAlarm')}}监听方法传入的参数对象{{WebExtAPIRef('alarms.Alarm')}}的name属性访问到。</dd>
+ <dd>Alarm的名称是唯一的 (在单个附件范围内). 如果传入了已经在这个附件存在的名称, 原来的同名alarm会被移除并且没有警告。</dd>
+ <dt><code>alarmInfo</code>{{optional_inline}}</dt>
+ <dd>
+ <p><code>对象(object)类型</code>. 你可以对过它来指定什么时间alarm会开始触发,其值可以是一个具体的时间值或者是一个延时(从alarm设置开始)。为了让alarm能复现,需要指定<code>periodInMinutes。</code></p>
+
+ <p>在Chrome浏览器上,除非附件以非打包(unpackaged)方式加载,alarm的创建每分钟不允许超过一次。如果附件尝试设置<code>delayInMinutes</code><code>为小于1的值,alarm只能在到达1分钟之后才会触发,并且会变成每分钟触发一次。</code></p>
+
+ <p><code>alarmInfo对象</code>可以设置以下属性:</p>
+ </dd>
+ <dd>
+ <dl class="reference-values">
+ <dt><code>when</code>{{optional_inline}}</dt>
+ <dd><code>double类型</code>. alarm第一次触发的时间,值为自1970-01-01 00:00:00 UTC过去的毫秒数。请使用<code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now">Date.now()</a>来获取</code>1970-01-01 00:00:00 UTC到<code>当前时间过去的毫秒数。如果你设置了when属性,请不要设置delayInMinutes属性。</code></dd>
+ <dt><code>delayInMinutes</code>{{optional_inline}}</dt>
+ <dd><code>double类型</code>. alarm设置好到第一次触发之间的分钟数。如果你设置了<code>delayInMinutes属性,请不要设置when属性。</code></dd>
+ <dt><code>periodInMinutes</code>{{optional_inline}}</dt>
+ <dd><code>double类型</code>. 如果设置此属性,alarm会从第一次触发开始每隔<code>periodInMinutes分钟再次触发。如果你没有设置when及delayInMinutes属性,alarm会在alarm设置好之后periodInMinutes分钟第一次触发。如果periodInMinutes属性没有设置,则alarm只会触发一次。</code></dd>
+ </dl>
+ </dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.alarms.create")}}</p>
+
+<h2 id="示例">示例</h2>
+
+<p>Create a one-time delay-based alarm with "" for the name:</p>
+
+<pre class="brush: js">const delayInMinutes = 5;
+
+<span class="pl-smi">browser</span>.<span class="pl-smi">alarms</span>.<span class="pl-en">create</span>({
+ delayInMinutes
+});</pre>
+
+<p>Create a periodic delay-based alarm named "my-periodic-alarm":</p>
+
+<pre class="brush: js">const delayInMinutes = 5;
+const periodInMinutes = 2;
+
+browser.alarms.create("my-periodic-alarm", {
+ delayInMinutes,
+ periodInMinutes
+});</pre>
+
+<p>Create a periodic absolute alarm named "my-periodic-alarm":</p>
+
+<pre class="brush: js">const when = 1545696000;
+const periodInMinutes = 2;
+
+browser.alarms.create("my-periodic-alarm", {
+ when,
+ periodInMinutes
+});</pre>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/alarms"><code>chrome.alarms</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/alarms/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/alarms/index.html
new file mode 100644
index 0000000000..66b7c52339
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/alarms/index.html
@@ -0,0 +1,58 @@
+---
+title: alarms
+slug: Mozilla/Add-ons/WebExtensions/API/alarms
+translation_of: Mozilla/Add-ons/WebExtensions/API/alarms
+---
+<div>{{AddonSidebar}}</div>
+
+<p>在未来一个特定的时间运行的计划任务代码。这很像<code><a href="/zh-CN/docs/Web/API/WindowTimers/setTimeout">setTimeout()</a></code>和<code><a href="/zh-CN/docs/Web/API/WindowTimers/setInterval">setInterval()</a></code>,不过这些函数仅可以按需使用而不能在后台页面工作。</p>
+
+<p>想要使用这个API,您需要获取"alarms"的<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>。</p>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("alarms.Alarm")}}</dt>
+ <dd>Information about a particular alarm.</dd>
+</dl>
+
+<h2 id="方法">方法</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("alarms.create()")}}</dt>
+ <dd>创建新的alarm.</dd>
+ <dt>{{WebExtAPIRef("alarms.get()")}}</dt>
+ <dd>通过名称获取指定的alarm.</dd>
+ <dt>{{WebExtAPIRef("alarms.getAll()")}}</dt>
+ <dd>获取所有的alarm.</dd>
+ <dt>{{WebExtAPIRef("alarms.clear()")}}</dt>
+ <dd>清除指定名称的alarm.</dd>
+ <dt>{{WebExtAPIRef("alarms.clearAll()")}}</dt>
+ <dd>清除所有的alarm.</dd>
+</dl>
+
+<h2 id="事件">事件</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("alarms.onAlarm")}}</dt>
+ <dd>当alarm发生的时候触发.</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.alarms")}}</p>
+
+<div class="hidden note">
+<p>The "Chrome incompatibilities" section is included from <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> using the <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p>
+
+<p>If you need to update this content, edit <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, then shift-refresh this page to see your changes.</p>
+</div>
+
+<p> {{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/alarms"><code>chrome.alarms</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/bookmarktreenode/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/bookmarktreenode/index.html
new file mode 100644
index 0000000000..bec868a18d
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/bookmarktreenode/index.html
@@ -0,0 +1,81 @@
+---
+title: bookmarks.BookmarkTreeNode
+slug: Mozilla/Add-ons/WebExtensions/API/bookmarks/BookmarkTreeNode
+translation_of: Mozilla/Add-ons/WebExtensions/API/bookmarks/BookmarkTreeNode
+---
+<p>{{AddonSidebar()}}</p>
+
+<p>代表书签树中的一个节点(书签或文件夹),子节点在它们的父文件夹中按顺序排列。</p>
+
+<h2 id="类型">类型</h2>
+
+<p>这种类型的值都是对象。它们包含以下属性:</p>
+
+<dl class="reference-values">
+ <dt><code>id</code></dt>
+ <dd><code>string</code>. 节点的唯一标识符。唯一标识符在当前用户配置文件中保证唯一,并且在浏览器重新启动后仍然有效。</dd>
+ <dt><code>parentId</code>{{optional_inline}}</dt>
+ <dd><code>string</code>. 父节点的标识符(id)。根节点没有此属性。</dd>
+ <dt><code>index</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. 该节点在父文件夹中的位置(从 0 开始)。</dd>
+ <dt><code>url</code>{{optional_inline}}</dt>
+ <dd><code>string</code>. 当用户单击书签时打开的URL。文件夹没有此属性。</dd>
+ <dt><code>title</code></dt>
+ <dd><code>string</code>. 该节点显示的文字。</dd>
+ <dt><code>dateAdded</code>{{optional_inline}}</dt>
+ <dd><code>number</code>. 该节点创建的时间,表示为自 1970 年 1 月 1 日午夜至今所经过的毫秒数(new Date(dateAdded))。</dd>
+ <dt><code>dateGroupModified</code>{{optional_inline}}</dt>
+ <dd><code>number</code>. 该文件夹内容的上一次修改时间,表示为自 1970 年 1 月 1 日午夜至今所经过的毫秒数。</dd>
+ <dt><code>unmodifiable</code>{{optional_inline}}</dt>
+ <dd>{{WebExtAPIRef('bookmarks.BookmarkTreeNodeUnmodifiable')}}. 表示该节点不可修改的原因,"<var>managed</var>"表示该节点由系统管理员配置。如果该节点可以由用户和扩展程序修改(默认)则省略。</dd>
+ <dt><code>children</code>{{optional_inline}}</dt>
+ <dd><code>array</code> of <code>{{WebExtAPIRef('bookmarks.BookmarkTreeNode')}}</code>. 该节点的所有子节点(已排序)。</dd>
+</dl>
+
+<p> </p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.bookmarks.BookmarkTreeNode", 10)}}</p>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/bookmarks#type-BookmarkTreeNode"><code>chrome.bookmarks</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/bookmarks.json"><code>bookmarks.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/gettree/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/gettree/index.html
new file mode 100644
index 0000000000..10571a1642
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/gettree/index.html
@@ -0,0 +1,120 @@
+---
+title: bookmarks.getTree()
+slug: Mozilla/Add-ons/WebExtensions/API/bookmarks/getTree
+tags:
+ - API
+ - WebExtensions
+ - getTree
+ - 书签
+ - 参考
+ - 拓展
+ - 方法
+ - 附件
+ - 非标准
+translation_of: Mozilla/Add-ons/WebExtensions/API/bookmarks/getTree
+---
+<div>{{AddonSidebar()}}</div>
+
+<p><strong><code>bookmarks.getTree()</code></strong> 返回一个数组,该数组每一项为{{WebExtAPIRef("bookmarks.BookmarkTreeNode")}}对象,作为书签树的根节点。</p>
+
+<p>如果它们是文件夹的话,你可以通过其<code>children属性及其后代的children属性</code>递归地访问整个树。</p>
+
+<p>这是一个异步的函数,返回<code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>。</code></p>
+
+<h2 id="使用格式">使用格式</h2>
+
+<pre class="syntaxbox brush:js">var gettingTree = browser.bookmarks.getTree()
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<p>无。</p>
+
+<h3 id="返回值">返回值</h3>
+
+<p><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>对象,该对象未来会得到一个填充代表根节点的</code><code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/bookmarks/BookmarkTreeNode" title="An object of type bookmarks.BookmarkTreeNode represents a node in the bookmark tree, where each node is a bookmark or bookmark folder. Child nodes are ordered by an index within their respective parent folders.">bookmarks.BookmarkTreeNode</a>对象的数组。</code></p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p> </p>
+
+<p>{{Compat("webextensions.api.bookmarks.getTree")}}</p>
+
+<p> </p>
+
+<h2 id="示例">示例</h2>
+
+<p>这个示例会打印出整个书签树:</p>
+
+<pre class="brush: js">function makeIndent(indentLength) {
+ return ".".repeat(indentLength);
+}
+
+function logItems(bookmarkItem, indent) {
+ if (bookmarkItem.url) {
+ console.log(makeIndent(indent) + bookmarkItem.url);
+ } else {
+ console.log(makeIndent(indent) + "Folder");
+ indent++;
+ }
+ if (bookmarkItem.children) {
+ for (child of bookmarkItem.children) {
+ logItems(child, indent);
+ }
+ }
+ indent--;
+}
+
+function logTree(bookmarkItems) {
+ logItems(bookmarkItems[0], 0);
+}
+
+function onRejected(error) {
+  console.log(`An error: ${error}`);
+}
+
+var gettingTree = browser.bookmarks.getTree();
+gettingTree.then(logTree, onRejected);
+</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/bookmarks#method-getTree"><code>chrome.bookmarks</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/bookmarks.json"><code>bookmarks.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/index.html
new file mode 100644
index 0000000000..06155a5972
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/index.html
@@ -0,0 +1,128 @@
+---
+title: bookmarks
+slug: Mozilla/Add-ons/WebExtensions/API/bookmarks
+translation_of: Mozilla/Add-ons/WebExtensions/API/bookmarks
+---
+<div>{{AddonSidebar}}</div>
+
+<p>此<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions">WebExtensions</a> {{WebExtAPIRef("bookmarks")}} API允许一个附加组件和浏览器的书签系统交互和操作。您可以用它给页面加书签,获取已有的书签,以及编辑,移除和管理书签。</p>
+
+<p>欲使用此API,一个附件组件必须请求"bookmarks" <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>在它的<code><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a></code>文件当中。</p>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("bookmarks.BookmarkTreeNode")}}</dt>
+ <dd>表示在书签树中的一个书签或者文件夹。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.BookmarkTreeNodeType")}}</dt>
+ <dd>一个描述在树中的一个节点是否是一个书签,一个文件夹或是一个分割符的 {{jsxref("String")}} 枚举类型。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.BookmarkTreeNodeUnmodifiable")}}</dt>
+ <dd>一个说明了为什么一个书签或者文件夹是不可修改的 {{jsxref("String")}} 枚举类型。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.CreateDetails")}}</dt>
+ <dd>当创建一个新书签时,包含被传递给这个 {{WebExtAPIRef("bookmarks.create()")}} 函数的信息。</dd>
+</dl>
+
+<dl>
+</dl>
+
+<h2 id="方法">方法</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("bookmarks.create()")}}</dt>
+ <dd>创建一个书签或文件夹。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.get()")}}</dt>
+ <dd>获得一个或者多个{{WebExtAPIRef("bookmarks.BookmarkTreeNode", "BookmarkTreeNode")}},提供一个书签的编号或者一个书签编号的数组。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.getChildren()")}}</dt>
+ <dd>获取指定{{WebExtAPIRef("bookmarks.BookmarkTreeNode", "BookmarkTreeNode")}}节点的所有子节点。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.getRecent()")}}</dt>
+ <dd>获取最近添加的几个书签。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.getSubTree()")}}</dt>
+ <dd>获取从指定节点开始的部分书签树。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.getTree()")}}</dt>
+ <dd>获取整个书签树。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.search()")}}</dt>
+ <dd>搜索书签树节点,找出匹配的结果。如果以对象方式指定查询,得到的 BookmarkTreeNodes 匹配所有指定的属性。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.create()")}}</dt>
+ <dd>在指定的上一级文件夹下创建新的书签或文件夹。如果 url 为 null 或者省略,则创建文件夹。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.move()")}}</dt>
+ <dd>将指定的书签树节点移到指定位置</dd>
+ <dt>{{WebExtAPIRef("bookmarks.update()")}}</dt>
+ <dd>更新书签或文件夹的属性。只需要指定您需要更改的属性,未指定的属性不会更改。注意:目前只支持“title”和“url”属性。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.remove()")}}</dt>
+ <dd>删除书签或者空文件夹。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.removeTree()")}}</dt>
+ <dd>删除整个书签文件夹。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.import()")}}</dt>
+ <dd>从一个html书签文件导入书签</dd>
+ <dt>{{WebExtAPIRef("bookmarks.export()")}}</dt>
+ <dd>导出书签为一个html书签文件</dd>
+</dl>
+
+<h2 id="事件">事件</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("bookmarks.onCreated")}}</dt>
+ <dd>当书签或文件夹创建时产生。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.onRemoved")}}</dt>
+ <dd>当删除书签或文件夹时产生。当删除整个文件夹(包括其中所有内容)时,仅为该文件夹发送通知,不为其中任何内容发送通知。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.onChanged")}}</dt>
+ <dd>一个书签或文件夹更改时发生。注意:目前只有标题和URL更改时会触发这一事件。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.onMoved")}}</dt>
+ <dd>当书签或文件夹移动到另一个父文件夹中时产生。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.onChildrenReordered")}}</dt>
+ <dd>文件夹中的子节点在用户界面中调整顺序时产生。调用 move() 不会触发该事件。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.onImportBegan")}}</dt>
+ <dd>开始导入书签时产生。复杂的事件处理函数在这一事件产生后不应该再处理 onCreated 事件,直到 onImportEnded 事件产生,在此过程中其他事件仍然应该立即处理。</dd>
+ <dt>{{WebExtAPIRef("bookmarks.onImportEnded")}}</dt>
+ <dd>书签导入结束时产生。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.bookmarks")}}</p>
+
+<div class="hidden note">
+<p>The "Chrome incompatibilities" section is included from <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> using the <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p>
+
+<p>If you need to update this content, edit <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, then shift-refresh this page to see your changes.</p>
+</div>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/bookmarks"><code>chrome.bookmarks</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/bookmarks.json"><code>bookmarks.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/remove/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/remove/index.html
new file mode 100644
index 0000000000..ee23ed285e
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/bookmarks/remove/index.html
@@ -0,0 +1,106 @@
+---
+title: bookmarks.remove()
+slug: Mozilla/Add-ons/WebExtensions/API/bookmarks/remove
+tags:
+ - API
+ - Add-ons
+ - Bookmarks
+ - Method
+ - remove
+ - 书签
+ - 参考文档
+ - 扩展
+ - 方法
+ - 移除
+translation_of: Mozilla/Add-ons/WebExtensions/API/bookmarks/remove
+---
+<div>{{AddonSidebar()}}</div>
+
+<p> <strong><code>bookmarks.remove()</code></strong> 方法用于删除单个书签或一个空的书签文件夹。</p>
+
+<div class="blockIndicator warning">
+<p>如果你的扩展尝试从书签树的根节点中移除一个书签,该调用将会引发一个“书签根不能被修改的”的错误信息并且这个书签不会被移除。</p>
+</div>
+
+<p><code>这是一个异步方法,返回<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>对象。</code></p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">var removingBookmark = browser.bookmarks.remove(
+ id // 字符串
+)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>id</code></dt>
+ <dd>{{jsxref("string")}} 要删除的书签或空书签文件夹的id标识</dd>
+</dl>
+
+<h3 id="返回值">返回值</h3>
+
+<p>若方法执行完成,返回一个无参的 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>对象。</code></p>
+
+<p>若未找到该书签或该空书签文件夹,将返回一个带有错误信息的<code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>对象。</code></p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.bookmarks.remove")}}</p>
+
+<h2 id="例子">例子</h2>
+
+<pre class="brush: js">function onRemoved() {
+ console.log("Removed!");
+}
+
+function onRejected(error) {
+ console.log(`An error: ${error}`);
+}
+
+var bookmarkId = "abcdefghijkl";
+
+var removingBookmark = browser.bookmarks.remove(bookmarkId);
+removingBookmark.then(onRemoved, onRejected);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/bookmarks#method-remove"><code>chrome.bookmarks</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/bookmarks.json"><code>bookmarks.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/browseraction/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/browseraction/index.html
new file mode 100644
index 0000000000..2d49dff094
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/browseraction/index.html
@@ -0,0 +1,116 @@
+---
+title: browserAction
+slug: Mozilla/Add-ons/WebExtensions/API/browserAction
+translation_of: Mozilla/Add-ons/WebExtensions/API/browserAction
+---
+<div>{{AddonSidebar}}</div>
+
+<p>添加按钮到浏览器的工具栏。</p>
+
+<p>您可以为该按钮指派一个弹出窗。弹出窗可采用 HTML、CSS 和 JavaScript 编写,就像是一个普通的网页。运行在该弹出窗中的 JavaScript 可以同您的后台脚本一样访问所有的 WebExtension API,但它的全局上下文是该弹出窗,而不是浏览器中的当前页面。要影响网页,您需要通过<a href="/en-US/Add-ons/WebExtensions/Modify_a_web_page#Messaging">消息</a>通信。</p>
+
+<p>如果您指定了弹出窗,它将显示——内容将在用户点击该图标时被加载。如果您没有指定一个弹出窗,用户单击该图标的事件将派发到您的扩展。</p>
+
+<p>您可以用 manifest.json 中的 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code> 键值声明定义大多数浏览器动作属性。</p>
+
+<p>使用 <code>browserAction</code> API,您可以:</p>
+
+<ul>
+ <li>使用 {{WebExtAPIRef("browserAction.onClicked")}} 监听该图标的点击事件。</li>
+ <li>获取和设置该图标的属性——图标、标题、弹出窗等。 You can get and set these globally across all tabs, or for a specific tab by passing the tab ID as an additional argument.</li>
+</ul>
+
+<p>另见<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/User_interface_components">用户界面组件</a>中的浏览器动作章节。</p>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("browserAction.ColorArray")}}</dt>
+ <dd>0-255范围内的四个整数的数组,定义RGBA颜色。</dd>
+ <dt>{{WebExtAPIRef("browserAction.ImageDataType")}}</dt>
+ <dd>一个图像的像素数据。必须为一个 <code><a href="/en-US/docs/Web/API/ImageData">ImageData</a></code> 对象(例如,来自一个 {{htmlelement("canvas")}} 元素)。</dd>
+</dl>
+
+<h2 id="函数">函数</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("browserAction.setTitle()")}}</dt>
+ <dd>设置浏览器动作的标题。这将在工具提示(鼠标悬停时)显示。</dd>
+ <dt>{{WebExtAPIRef("browserAction.getTitle()")}}</dt>
+ <dd>获取浏览器动作的标题。</dd>
+ <dt>{{WebExtAPIRef("browserAction.setIcon()")}}</dt>
+ <dd>设置浏览器动作的图标。</dd>
+ <dt>{{WebExtAPIRef("browserAction.setPopup()")}}</dt>
+ <dd>设置 HTML 文档作为浏览器动作图标被用户点击时显示的弹出窗。</dd>
+ <dt>{{WebExtAPIRef("browserAction.getPopup()")}}</dt>
+ <dd>获取作为浏览器动作的弹出窗的 HTML 文档。</dd>
+ <dt>{{WebExtAPIRef("browserAction.setBadgeText()")}}</dt>
+ <dd>设置浏览器动作的徽章文本。该徽章显示在图标上方。</dd>
+ <dt>{{WebExtAPIRef("browserAction.getBadgeText()")}}</dt>
+ <dd>获取浏览器动作的徽章文本。</dd>
+ <dt>{{WebExtAPIRef("browserAction.setBadgeBackgroundColor()")}}</dt>
+ <dd>设置徽章的后台颜色。</dd>
+ <dt>{{WebExtAPIRef("browserAction.getBadgeBackgroundColor()")}}</dt>
+ <dd>获取徽章的后台颜色。</dd>
+ <dt>{{WebExtAPIRef("browserAction.enable()")}}</dt>
+ <dd>为一个标签页启用浏览器动作。默认情况下,浏览器动作为所有标签页启用。</dd>
+ <dt>{{WebExtAPIRef("browserAction.disable()")}}</dt>
+ <dd>为一个标签页禁用浏览器动作,使该标签页为活动时无法单击它。</dd>
+</dl>
+
+<h2 id="事件">事件</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("browserAction.onClicked")}}</dt>
+ <dd>在浏览器动作图标点击时被触发。如果浏览器动作有弹出窗,则该事件不会触发。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.browserAction")}}</p>
+
+<div class="hidden note">
+<p>"Chrome兼容性"是从 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> 包含,使用<a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a>宏。</p>
+
+<p>如果你需要更新此章节,编辑 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>,然后刷新查看更改。</p>
+</div>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>致谢</strong>
+
+<p>此 API 基于 Chromium 的 <a href="https://developer.chrome.com/extensions/browserAction"><code>chrome.browserAction</code></a> API。此文档派生自 Chromium 代码中的 <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/browser_action.json"><code>browser_action.json</code></a>。</p>
+
+<p>Microsoft Edge 兼容性数据由微软公司提供,并以 知识共享 署名 3.0 美国版 许可。</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/index.html
new file mode 100644
index 0000000000..f58017fba8
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/index.html
@@ -0,0 +1,90 @@
+---
+title: captivePortal
+slug: Mozilla/Add-ons/WebExtensions/API/captivePortal
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - NeedsTranslation
+ - Non-standard
+ - Reference
+ - TopicStub
+ - WebExtensions
+ - captivePortal
+translation_of: Mozilla/Add-ons/WebExtensions/API/captivePortal
+---
+<div>{{AddonSidebar}}</div>
+
+<p>Determine the captive portal state of the user’s connection. A captive portal is a web page displayed when a user first connects to a Wi-Fi network. The user provides information or acts on the captive portal web page to gain broader access to network resources, such as accepting terms and conditions or making a payment. </p>
+
+<p>To use this API you need to have the "captivePortal" <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>.</p>
+
+<h2 id="Properties">Properties</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("captivePortal.canonicalURL")}}</dt>
+ <dd>Return the canonical URL of the captive-portal detection page. Read-only.</dd>
+</dl>
+
+<h2 id="Functions">Functions</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("captivePortal.getLastChecked()")}}</dt>
+ <dd>Returns the time, in milliseconds, since the last request was completed.</dd>
+ <dt>{{WebExtAPIRef("captivePortal.getState()")}}</dt>
+ <dd>Returns the portal state as one of <code>unknown</code>, <code>not_captive</code>, <code>unlocked_portal</code>, or <code>locked_portal</code>.</dd>
+</dl>
+
+<h2 id="Events">Events</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("captivePortal.onConnectivityAvailable")}}</dt>
+ <dd>Fires when the captive portal service determines that the user can connect to the internet.</dd>
+ <dt>{{WebExtAPIRef("captivePortal.onStateChanged")}}</dt>
+ <dd>
+ <p>Fires when the captive portal state changes.</p>
+ </dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.captivePortal")}}</p>
+
+<div class="hidden note">
+<p>The "Chrome incompatibilities" section is included from <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> using the <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p>
+
+<p>If you need to update this content, edit <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, then shift-refresh this page to see your changes.</p>
+</div>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/onstatechanged/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/onstatechanged/index.html
new file mode 100644
index 0000000000..3211026253
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/captiveportal/onstatechanged/index.html
@@ -0,0 +1,94 @@
+---
+title: onStateChanged
+slug: Mozilla/Add-ons/WebExtensions/API/captivePortal/onStateChanged
+translation_of: Mozilla/Add-ons/WebExtensions/API/captivePortal/onStateChanged
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>Fires when the captive portal state changes.</p>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js">browser.captivePortal.onStateChanged.addListener(callback)
+browser.captivePortal.onStateChanged.removeListener(listener)
+browser.captivePortal.onStateChanged.hasListener(listener)
+</pre>
+
+<p>Events have three functions:</p>
+
+<dl>
+ <dt><code>addListener(callback)</code></dt>
+ <dd>Adds a listener to this event.</dd>
+ <dt><code>removeListener(listener)</code></dt>
+ <dd>Stop listening to this event. The <code>listener</code> argument is the listener to remove.</dd>
+ <dt><code>hasListener(listener)</code></dt>
+ <dd>Check whether <code>listener</code> is registered for this event. Returns <code>true</code> if it is listening, <code>false</code> otherwise.</dd>
+</dl>
+
+<h2 id="addListener_syntax">addListener syntax</h2>
+
+<h3 id="Parameters">Parameters</h3>
+
+<dl>
+ <dt><code>callback</code></dt>
+ <dd>
+ <p>Function that is called when this event occurs. The function is passed the following arguments:</p>
+
+ <dl class="reference-values">
+ <dt><code>details</code></dt>
+ <dd>
+ <p><code>string</code> The captive portal state, being one of <code>unknown</code>, <code>not_captive</code>, <code>unlocked_portal</code>, or <code>locked_portal</code>.</p>
+ </dd>
+ </dl>
+ </dd>
+</dl>
+
+<h2 id="Examples">Examples</h2>
+
+<p>Handle a change in captive portal status:</p>
+
+<pre class="brush: js">function handlePortalStatus(portalstatusInfo) {
+ console.log("The portal status is now: " + portalstatusInfo.details);
+}
+
+browser.captivePortal.onStateChanged.addListener(handlePortalStatus)
+</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.captivePortal.onStateChanged")}}</p>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/contentscripts/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/contentscripts/index.html
new file mode 100644
index 0000000000..544b32d556
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/contentscripts/index.html
@@ -0,0 +1,41 @@
+---
+title: contentScripts
+slug: Mozilla/Add-ons/WebExtensions/API/contentScripts
+tags:
+ - API
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/API/contentScripts
+---
+<div>{{AddonSidebar}}</div>
+
+<p>使用此 API 以注册内容脚本。“注册内容脚本”意味着浏览器会将给定的内容脚本插入到每个与给定的 URL 模式相匹配的页面中。</p>
+
+<p>此 API 与 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a></code> 的  <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts">"content_scripts"</a></code> 键非常相似,但  <code>"content_scripts"</code> 键所能注册的内容脚本是固定的,自拓展安装后便不可更改。但<span class="seoSummary">通过 <code>contentScripts</code> API,拓展可以在运行时动态地注册或取消注册脚本。</span></p>
+
+<p>To use the API, call {{WebExtAPIRef("contentScripts.register()")}} passing in an object defining the scripts to register, the URL patterns, and other options. This returns a <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> that is resolved with a {{WebExtAPIRef("contentScripts.RegisteredContentScript")}} object.</p>
+
+<p>The <code>RegisteredContentScript</code> object represents the scripts that were registered in the <code>register()</code> call. It defines an <code>unregister()</code> method that you can use to unregister the content scripts. Content scripts are also unregistered automatically when the page that created them is destroyed. For example, if they are registered from the background page they will be unregistered automatically when the background page is destroyed, and if they are registered from a sidebar or a popup, they will be unregistered automatically when the sidebar or popup is closed.</p>
+
+<p>没有与 <code>contentScripts</code> API 相关联的权限,但是拓展必须拥有与其试图通过 <code>register()</code> 注册的脚本的匹配模式相对应的<a href="/zh-CN/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">主机权限</a>,才能实现注入。</p>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("contentScripts.RegisteredContentScript")}}</dt>
+ <dd>
+ <p>{{WebExtAPIRef("contentScripts.register()")}} 函数会返回一个持有此类型的对象。它表示被通过调用此函数注册的内容脚本,可被用于取消注册对应的内容脚本。</p>
+ </dd>
+</dl>
+
+<h2 id="函数">函数</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("contentScripts.register()")}}</dt>
+ <dd>注册给定的内容脚本。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.contentScripts", 10, 1)}}</p>
+
+<p>{{WebExtExamples("h2")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/contextmenus/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/contextmenus/index.html
new file mode 100644
index 0000000000..ffcb6ce7b7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/contextmenus/index.html
@@ -0,0 +1,191 @@
+---
+title: contextMenus
+slug: Mozilla/Add-ons/WebExtensions/API/contextMenus
+tags:
+ - API
+ - WebExtensions
+ - contextMenus
+translation_of: Mozilla/Add-ons/WebExtensions/API/menus
+---
+<div>{{AddonSidebar}}</div>
+
+<div>在浏览器菜单中添加条目。</div>
+
+<div></div>
+
+<div>此API基于Chrome的“contextMenus”API构建,该API可让Chrome扩展程序将项目添加到浏览器的上下文菜单中。 <code>browser.menus</code> API为Chrome的API添加了一些功能,特别是可以将项目添加到浏览器的“工具”菜单以及上下文菜单中。</div>
+
+<div></div>
+
+<div>在Firefox 55之前,这个API最初也被命名为<code>contextMenus</code>,并且这个名字被保留为别名,所以你可以使用<code>contextMenus</code>编写在Firefox和其他浏览器中工作的代码。</div>
+
+<div></div>
+
+<div>你需要拥有“menus”(或别名" contextMenus ")权限来使用此API。</div>
+
+<h2 id="创建菜单项">创建菜单项</h2>
+
+<p>使用 {{WebExtAPIRef("menus.create()")}}方法创建一个菜单项。你需要传递一个包含条目选项的对象,它包括条目的id,类型,和需要显示出来的文本值。</p>
+
+<p>绑定一个监听器到{{WebExtAPIRef("contextMenus.onClicked")}}事件来监听你菜单项目的点击事件。此监听器会传递一个{{WebExtAPIRef("contextMenus.OnClickData")}},它包含该事件的详细信息。</p>
+
+<p>你可以根据在调用<code>create()</code>时所传递的参数中使用不同的<code>type</code>值来创建四种不同类型的菜单:</p>
+
+<ul>
+ <li>"normal":只显示为一个标签的菜单项</li>
+ <li>"checkbox":一个表示二进制状态的菜单项。 它在菜单项旁边显示一个复选标记。 点击该菜单项切换复选标记。监听器会被传递两个额外的属性:“checked”,指示当前是否被选中,以及“wasChecked”,指示在此点击事件发生前是否被选中。</li>
+ <li>"radio":表示一组选项之一的上下文菜单项。 类似于复选框,它也在菜单项旁边显示一个复选标记,监听它的监听器也会被传递“checked”和“wasChecked”。 但是,如果您创建多个单选项,则这些项目将作为一组单选:组内只能选择一项,点击菜单项来选中它。</li>
+ <li>"separator":用于分割菜单的分割线。</li>
+</ul>
+
+<p>如果您创建了多个上下文菜单项目或多个工具菜单项目,则这些项目将被放置在子菜单中。 子菜单的父项将标有扩展名。 例如,下面是一个名为“Menu Demo”的扩展,添加了两个上下文菜单项:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15431/menus-1.png" style="display: block; height: 501px; margin-left: auto; margin-right: auto; width: 700px;"></p>
+
+<h2 id="图标">图标</h2>
+
+<p>如果你使用 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/icons">"icons" manifest key</a> 为你的扩展指定一个图标,你的菜单项的旁边就会显示一个指定的图标。浏览器会尝试在普通分辨率下使用16 x 16像素的图标,在高分辨率下使用32 x 32像素的图标:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15433/menus-2.png" style="display: block; height: 409px; margin-left: auto; margin-right: auto; width: 500px;"> 你可以通过调用 {{WebExtAPIRef("menus.create()")}} 时指定icons选项来给子菜单项设置图标。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15435/menus-3.png" style="display: block; height: 396px; margin-left: auto; margin-right: auto; width: 500px;"></p>
+
+<h2 id="例子">例子</h2>
+
+<p>下面是一个包含四个项目的菜单,他们分别是:一个普通选项,两个周围有分割线的单选,和一个复选框。单选框使用了自定义图标。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15437/menus-4.png" style="display: block; height: 790px; margin-left: auto; margin-right: auto; width: 500px;"></p>
+
+<p>你可以使用以下代码创建一个这样的子菜单:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js">browser<span class="punctuation token">.</span>menus<span class="punctuation token">.</span><span class="function token">create</span><span class="punctuation token">(</span><span class="punctuation token">{</span>
+ id<span class="punctuation token">:</span> <span class="string token">"remove-me"</span><span class="punctuation token">,</span>
+ title<span class="punctuation token">:</span> browser<span class="punctuation token">.</span>i18n<span class="punctuation token">.</span><span class="function token">getMessage</span><span class="punctuation token">(</span><span class="string token">"menuItemRemoveMe"</span><span class="punctuation token">)</span><span class="punctuation token">,</span>
+ contexts<span class="punctuation token">:</span> <span class="punctuation token">[</span><span class="string token">"all"</span><span class="punctuation token">]</span>
+<span class="punctuation token">}</span><span class="punctuation token">,</span> onCreated<span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+browser<span class="punctuation token">.</span>menus<span class="punctuation token">.</span><span class="function token">create</span><span class="punctuation token">(</span><span class="punctuation token">{</span>
+ id<span class="punctuation token">:</span> <span class="string token">"separator-1"</span><span class="punctuation token">,</span>
+ type<span class="punctuation token">:</span> <span class="string token">"separator"</span><span class="punctuation token">,</span>
+ contexts<span class="punctuation token">:</span> <span class="punctuation token">[</span><span class="string token">"all"</span><span class="punctuation token">]</span>
+<span class="punctuation token">}</span><span class="punctuation token">,</span> onCreated<span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+browser<span class="punctuation token">.</span>menus<span class="punctuation token">.</span><span class="function token">create</span><span class="punctuation token">(</span><span class="punctuation token">{</span>
+ id<span class="punctuation token">:</span> <span class="string token">"greenify"</span><span class="punctuation token">,</span>
+ type<span class="punctuation token">:</span> <span class="string token">"radio"</span><span class="punctuation token">,</span>
+ title<span class="punctuation token">:</span> browser<span class="punctuation token">.</span>i18n<span class="punctuation token">.</span><span class="function token">getMessage</span><span class="punctuation token">(</span><span class="string token">"menuItemGreenify"</span><span class="punctuation token">)</span><span class="punctuation token">,</span>
+ contexts<span class="punctuation token">:</span> <span class="punctuation token">[</span><span class="string token">"all"</span><span class="punctuation token">]</span><span class="punctuation token">,</span>
+ checked<span class="punctuation token">:</span> <span class="keyword token">true</span><span class="punctuation token">,</span>
+ icons<span class="punctuation token">:</span> <span class="punctuation token">{</span>
+ <span class="string token">"16"</span><span class="punctuation token">:</span> <span class="string token">"icons/paint-green-16.png"</span><span class="punctuation token">,</span>
+ <span class="string token">"32"</span><span class="punctuation token">:</span> <span class="string token">"icons/paint-green-32.png"</span>
+ <span class="punctuation token">}</span>
+<span class="punctuation token">}</span><span class="punctuation token">,</span> onCreated<span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+browser<span class="punctuation token">.</span>menus<span class="punctuation token">.</span><span class="function token">create</span><span class="punctuation token">(</span><span class="punctuation token">{</span>
+ id<span class="punctuation token">:</span> <span class="string token">"bluify"</span><span class="punctuation token">,</span>
+ type<span class="punctuation token">:</span> <span class="string token">"radio"</span><span class="punctuation token">,</span>
+ title<span class="punctuation token">:</span> browser<span class="punctuation token">.</span>i18n<span class="punctuation token">.</span><span class="function token">getMessage</span><span class="punctuation token">(</span><span class="string token">"menuItemBluify"</span><span class="punctuation token">)</span><span class="punctuation token">,</span>
+ contexts<span class="punctuation token">:</span> <span class="punctuation token">[</span><span class="string token">"all"</span><span class="punctuation token">]</span><span class="punctuation token">,</span>
+ checked<span class="punctuation token">:</span> <span class="keyword token">false</span><span class="punctuation token">,</span>
+ icons<span class="punctuation token">:</span> <span class="punctuation token">{</span>
+ <span class="string token">"16"</span><span class="punctuation token">:</span> <span class="string token">"icons/paint-blue-16.png"</span><span class="punctuation token">,</span>
+ <span class="string token">"32"</span><span class="punctuation token">:</span> <span class="string token">"icons/paint-blue-32.png"</span>
+ <span class="punctuation token">}</span>
+<span class="punctuation token">}</span><span class="punctuation token">,</span> onCreated<span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+browser<span class="punctuation token">.</span>menus<span class="punctuation token">.</span><span class="function token">create</span><span class="punctuation token">(</span><span class="punctuation token">{</span>
+ id<span class="punctuation token">:</span> <span class="string token">"separator-2"</span><span class="punctuation token">,</span>
+ type<span class="punctuation token">:</span> <span class="string token">"separator"</span><span class="punctuation token">,</span>
+ contexts<span class="punctuation token">:</span> <span class="punctuation token">[</span><span class="string token">"all"</span><span class="punctuation token">]</span>
+<span class="punctuation token">}</span><span class="punctuation token">,</span> onCreated<span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+<span class="keyword token">var</span> checkedState <span class="operator token">=</span> <span class="keyword token">true</span><span class="punctuation token">;</span>
+
+browser<span class="punctuation token">.</span>menus<span class="punctuation token">.</span><span class="function token">create</span><span class="punctuation token">(</span><span class="punctuation token">{</span>
+ id<span class="punctuation token">:</span> <span class="string token">"check-uncheck"</span><span class="punctuation token">,</span>
+ type<span class="punctuation token">:</span> <span class="string token">"checkbox"</span><span class="punctuation token">,</span>
+ title<span class="punctuation token">:</span> browser<span class="punctuation token">.</span>i18n<span class="punctuation token">.</span><span class="function token">getMessage</span><span class="punctuation token">(</span><span class="string token">"menuItemUncheckMe"</span><span class="punctuation token">)</span><span class="punctuation token">,</span>
+ contexts<span class="punctuation token">:</span> <span class="punctuation token">[</span><span class="string token">"all"</span><span class="punctuation token">]</span><span class="punctuation token">,</span>
+ checked<span class="punctuation token">:</span> checkedState
+<span class="punctuation token">}</span><span class="punctuation token">,</span> onCreated<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("contextMenus.ContextType")}}</dt>
+ <dd>菜单里可以出现的不同内容。可能的值有:"all", "audio", "browser_action", "editable", "frame", "image", "link", "page", "page_action", "password", "selection", "tab", "video".</dd>
+ <dt>{{WebExtAPIRef("contextMenus.ItemType")}}</dt>
+ <dd>菜单项的类别有: "normal", "checkbox", "radio", "separator".</dd>
+ <dt>{{WebExtAPIRef("contextMenus.OnClickData")}}</dt>
+ <dd>当菜单项被点击时发送的信息。</dd>
+</dl>
+
+<h2 id="属性">属性</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("contextMenus.ACTION_MENU_TOP_LEVEL_LIMIT")}}</dt>
+ <dd>可以被添加进上下文菜单项的顶级扩展项的最大值,其ContextType可以是"browser_action" 或者 "page_action".</dd>
+</dl>
+
+<h2 id="函数">函数</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("contextMenus.create()")}}</dt>
+ <dd>创建一个新的上下文菜单项目。</dd>
+ <dt>{{WebExtAPIRef("contextMenus.update()")}}</dt>
+ <dd>更新一个已经创建了的上下文菜单项目。</dd>
+ <dt>{{WebExtAPIRef("contextMenus.remove()")}}</dt>
+ <dd>删除一个上下文菜单项目。</dd>
+ <dt>{{WebExtAPIRef("contextMenus.removeAll()")}}</dt>
+ <dd>移除该插件创建的所有上下文菜单项目。</dd>
+</dl>
+
+<h2 id="事件">事件</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("contextMenus.onClicked")}}</dt>
+ <dd>当一个上下文菜单项被点击时触发。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{ Compat("webextensions.api.menus", 1, "true") }}</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>致谢</strong>
+
+<p>此API基于Chromium的 <a href="https://developer.chrome.com/extensions/contextMenus"><code>chrome.contextMenus</code></a> API. 此文档来自于Chromium代码中的<a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/context_menus.json"><code>context_menus.json</code></a>。</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/cookies/cookie/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/cookies/cookie/index.html
new file mode 100644
index 0000000000..1a5c4dfdd4
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/cookies/cookie/index.html
@@ -0,0 +1,121 @@
+---
+title: cookies.Cookie
+slug: Mozilla/Add-ons/WebExtensions/API/cookies/Cookie
+translation_of: Mozilla/Add-ons/WebExtensions/API/cookies/Cookie
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>The <code>Cookie</code> type of the {{WebExtAPIRef("cookies")}} API represents information about an HTTP cookie.</p>
+
+<h2 id="类型">类型</h2>
+
+<p>这玩意是一个 Object,可以包含以下的属性:</p>
+
+<dl class="reference-values">
+ <dt><code>domain</code></dt>
+ <dd>储存这个 cookie 对应网站的字符串 (例如 "www.tengxun.com")。</dd>
+ <dt><code>expirationDate</code>{{optional_inline}}</dt>
+ <dd>A <code>number</code> representing the expiration date of the cookie as the number of seconds since the UNIX epoch. Not provided for session cookies.</dd>
+ <dt><code>firstPartyDomain</code></dt>
+ <dd>A <code>string</code> representing the first-party domain associated with the cookie. This will be an empty string if the cookie was set while first-party isolation was off. See <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/cookies#First-party_isolation">First-party isolation</a>.</dd>
+ <dt><code>hostOnly</code></dt>
+ <dd>A <code>boolean</code>, <code>true</code> if the cookie is a host-only cookie (i.e. the request's host must exactly match the domain of the cookie), or <code>false</code> otherwise.</dd>
+ <dt><code>httpOnly</code></dt>
+ <dd>A <code>boolean</code>, <code>true</code> if the cookie is marked as HttpOnly (i.e. the cookie is inaccessible to client-side scripts), or <code>false</code> otherwise.</dd>
+ <dt><code>name</code></dt>
+ <dd>A <code>string</code> representing the name of the cookie.</dd>
+ <dt><code>path</code></dt>
+ <dd>A <code>string</code> representing the path of the cookie.</dd>
+ <dt><code>secure</code></dt>
+ <dd>A <code>boolean</code>, <code>true</code> if the cookie is marked as secure (i.e. its scope is limited to secure channels, typically HTTPS), or <code>false</code> otherwise.</dd>
+ <dt><code>session</code></dt>
+ <dd>A <code>boolean</code>, <code>true</code> if the cookie is a session cookie, or <code>false</code> if it is a persistent cookie with an expiration date.</dd>
+ <dt><code>sameSite</code></dt>
+ <dd>A {{WebExtAPIRef("cookies.SameSiteStatus")}} value that indicates the SameSite state of the cookie.</dd>
+ <dt><code>storeId</code></dt>
+ <dd>A <code>string</code> representing the ID of the cookie store containing this cookie, as provided by {{WebExtAPIRef("cookies.getAllCookieStores()")}}.</dd>
+ <dt><code>value</code></dt>
+ <dd>代表 cookie 的值的一个字符串。</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.cookies.Cookie")}}</p>
+
+<h2 id="举例">举例</h2>
+
+<p>Cookies API中的大多数方法都将 <code>Cookie</code> 对象用作输入参数或用作返回值的一部分。例如调用 {{WebExtAPIRef("cookies.getAll()")}} 将会返回一个 <code>Cookie</code> 对象的数组。</p>
+
+<p>在下面的例子中我们将会获取所有的 cookie ,然后 <code>console.log()</code> 出这些 <code>Cookie</code> 对象所对应的值。</p>
+
+<pre class="brush: js notranslate">function logCookies(cookies) {
+ for (cookie of cookies) {
+ console.log(`Domain: ${cookie.domain}`);
+ console.log(`Name: ${cookie.name}`);
+ console.log(`Value: ${cookie.value}`);
+ console.log(`Persistent: ${!cookie.session}`);
+ }
+}
+
+var gettingAll = browser.cookies.getAll({});
+gettingAll.then(logCookies);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>声明</strong>
+
+<p>这 API 是基于 Chromium 的 <a href="https://developer.chrome.com/extensions/cookies#type-Cookie"><code>chrome.cookies</code></a> API 的。 这个文档来自于 Chromium code 中的 <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/cookies.json"><code>cookies.json</code></a> 。</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate">// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
+
+<div id="simple-translate">
+<div>
+<div class="simple-translate-button isShow" style="height: 22px; width: 22px; top: 2528px; left: 464px;"></div>
+
+<div class="simple-translate-panel " style="width: 300px; height: 200px; top: 0px; left: 0px; font-size: 16px; background-color: rgb(17, 17, 17);">
+<div class="simple-translate-result-wrapper" style="overflow: hidden;">
+<div class="simple-translate-move"></div>
+
+<div class="simple-translate-result-contents">
+<p class="simple-translate-result" style="color: rgb(234, 234, 234);"></p>
+
+<p class="simple-translate-candidate" style="color: rgb(195, 195, 195);"></p>
+</div>
+</div>
+</div>
+</div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/cookies/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/cookies/index.html
new file mode 100644
index 0000000000..4011b4fe56
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/cookies/index.html
@@ -0,0 +1,151 @@
+---
+title: cookies
+slug: Mozilla/Add-ons/WebExtensions/API/cookies
+tags:
+ - API
+ - Add-ons
+ - Cookies
+ - Extensions
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/API/cookies
+---
+<div>{{AddonSidebar}}</div>
+
+<p>使用 WebExtensions 获取或设置 cookies, 并且在修改时能够获得通知。</p>
+
+<p>你需要在 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> 文件中开启“cookies”<a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">API 权限</a>,并且需要对应站点的 <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">主机权限</a> 才能设置指定站点的cookie。详细信息查看 <a href="/en-US/Add-ons/WebExtensions/API/cookies#Permissions">cookie 权限</a>.</p>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("cookies.Cookie")}}</dt>
+ <dd>代表一个HTTP cookie的信息。</dd>
+ <dt>{{WebExtAPIRef("cookies.CookieStore")}}</dt>
+ <dd>代表一个保存在浏览器中的 cookie。</dd>
+ <dt>{{WebExtAPIRef("cookies.OnChangedCause")}}</dt>
+ <dd>代表 cookie 改变的原因。</dd>
+</dl>
+
+<h2 id="方法">方法</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("cookies.get()")}}</dt>
+ <dd>返回一个单独的 cookie 的信息。</dd>
+ <dt>{{WebExtAPIRef("cookies.getAll()")}}</dt>
+ <dd>返回所有符合筛选条件的 cookies。</dd>
+ <dt>{{WebExtAPIRef("cookies.set()")}}</dt>
+ <dd>根据给定cookie数据设置一个cookie;如果同样的cookie存在讲会覆盖。</dd>
+ <dt>{{WebExtAPIRef("cookies.remove()")}}</dt>
+ <dd>根据名字删除cookie。</dd>
+ <dt>{{WebExtAPIRef("cookies.getAllCookieStores()")}}</dt>
+ <dd>列出所有保存的cookie。</dd>
+</dl>
+
+<h2 id="事件句柄">事件句柄</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("cookies.onChanged")}}</dt>
+ <dd>当设置或删除cookie时触发。</dd>
+</dl>
+
+<h2 id="权限">权限</h2>
+
+<p>为了使用这个API,插件必须在它的manifest中指定"cookies" <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">API 权限</a>,和它想要使用cookie的任何网站的 <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">host 权限</a> 。插件将能读取或写入host权限中所匹配的URL可以读取或写入的任何cookie。例如:</p>
+
+<dl>
+ <dt><code>http://*.example.com/</code></dt>
+ <dd>
+ <p>拥有这个host权限的插件将可以:</p>
+
+ <ul>
+ <li>读取一个<code>www.example.com</code>任意路径下的不安全cookie。</li>
+ <li>写入一个<code>www.example.com</code>任意路径下的不安全cookie。</li>
+ </ul>
+
+ <p><em>它不能:</em></p>
+
+ <ul>
+ <li>读取<code>www.example.com</code>的安全cookie。</li>
+ </ul>
+ </dd>
+ <dt><code>http://www.example.com/</code></dt>
+ <dd>
+ <p>拥有这个host权限的插件将可以:</p>
+
+ <ul>
+ <li>读取 <code>www.example.com</code>任意路径下的不安全cookie。</li>
+ <li>读取 <code>.example.com</code> 任意路径下的不安全cookie。</li>
+ <li>写入 <code>www.example.com</code> 任意路径下的安全和不安全cookie。</li>
+ <li>写入 <code>.example.com</code> 任意路径下的安全和不安全cookie。</li>
+ </ul>
+
+ <p>它不能:</p>
+
+ <ul>
+ <li>读取或写入 <code>foo.example.com</code> 的cookie。</li>
+ <li>读取或写入 <code>foo.www.example.com</code> 的cookie。</li>
+ </ul>
+ </dd>
+ <dt><code>*://*.example.com/</code></dt>
+ <dd>
+ <p>拥有这个host权限的插件将可以:</p>
+
+ <ul>
+ <li>读取或写入 <code>www.example.com</code> 任意路径下安全的和不安全的cookie。</li>
+ </ul>
+ </dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.cookies")}}</p>
+
+<div class="hidden note">
+<p>The "Chrome incompatibilities" section is included from <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> using the <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p>
+
+<p>If you need to update this content, edit <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, then shift-refresh this page to see your changes.</p>
+</div>
+
+<h3 id="Edge_不兼容">Edge 不兼容</h3>
+
+<p>在 Edge 中不支持 Promises,使用 callbacks 代替。</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>这个API 基于 Chromium 的 <a href="https://developer.chrome.com/extensions/cookies"><code>chrome.cookies</code></a> API. 这篇文档来源于Chromium 代码的 <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/cookies.json"><code>cookies.json</code></a> 。</p>
+
+<p>Microsoft Edge 兼容性数据由 Microsoft Corporation 提供,并包含在 Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/devtools.inspectedwindow/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/devtools.inspectedwindow/index.html
new file mode 100644
index 0000000000..d59f29ffde
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/devtools.inspectedwindow/index.html
@@ -0,0 +1,72 @@
+---
+title: devtools.inspectedWindow
+slug: Mozilla/Add-ons/WebExtensions/API/devtools.inspectedWindow
+translation_of: Mozilla/Add-ons/WebExtensions/API/devtools.inspectedWindow
+---
+<div>{{AddonSidebar}}</div>
+
+<div class="note">
+<p>This page describes the WebExtensions devtools APIs as they exist in Firefox 54. Although the APIs are based on the <a href="https://developer.chrome.com/extensions/devtools">Chrome devtools APIs</a>, there are still many features that are not yet implemented in Firefox, and therefore are not documented here. To see which features are currently missing please see <a href="/en-US/Add-ons/WebExtensions/Using_the_devtools_APIs#Limitations_of_the_devtools_APIs">Limitations of the devtools APIs</a>.</p>
+</div>
+
+<p>The <code>devtools.inspectedWindow</code> API lets a devtools extension interact with the window that the developer tools are attached to.</p>
+
+<p>Like all the <code>devtools</code> APIs, this API is only available to code running in the document defined in the <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/devtools_page">devtools_page</a> manifest.json key, or in other devtools documents created by the extension (such as the document hosted by a panel the extension created). See <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Extending_the_developer_tools">Extending the developer tools</a> for more.</p>
+
+<h2 id="Properties">Properties</h2>
+
+<dl>
+ <dt><code><a href="/en-US/Add-ons/WebExtensions/API/devtools.inspectedWindow/tabId">devtools.inspectedWindow.tabId</a></code></dt>
+ <dd>The ID of the window that the developer tools are attached to.</dd>
+</dl>
+
+<h2 id="Functions">Functions</h2>
+
+<dl>
+ <dt><code><a href="/en-US/Add-ons/WebExtensions/API/devtools.inspectedWindow/eval">devtools.inspectedWindow.eval()</a></code></dt>
+ <dd>Evaluate some JavaScript in the target window.</dd>
+ <dt><code><a href="/en-US/Add-ons/WebExtensions/API/devtools.inspectedWindow/reload">devtools.inspectedWindow.reload()</a></code></dt>
+ <dd>Reload the target window's document.</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.devtools.inspectedWindow")}}{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/devtools_inspectedWindow"><code>chrome.devtools.inspectedWindow</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/downloads/download/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/downloads/download/index.html
new file mode 100644
index 0000000000..c7b6216ee8
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/downloads/download/index.html
@@ -0,0 +1,144 @@
+---
+title: downloads.download()
+slug: Mozilla/Add-ons/WebExtensions/API/downloads/download
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - Method
+ - WebExtensions
+ - download
+ - downloads
+translation_of: Mozilla/Add-ons/WebExtensions/API/downloads/download
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>{{WebExtAPIRef("downloads")}} API 的 <strong><code>download()</code></strong> 函数根据给出的URL和其他首选项下载一个文件。</p>
+
+<ul>
+ <li>如果指定的 <code>url</code> 使用HTTP或者HTTPS协议, 那么下载请求将会包含当前为该域名所设置的所有cookie。</li>
+ <li>如果<code>filename</code> 和 <code>saveAs</code> 都已经指定,那么将会弹出“保存为” 对话框,并且默认名称显示为<code>filename</code>.</li>
+</ul>
+
+<p>这是一个异步函数,其返回值为 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>.</p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">var downloading = browser.downloads.download(
+ options // object
+)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>options</code></dt>
+ <dd>一个 <code>object</code> ,用来指定你想要下载的文件和其他想要在下载时设置的首选项。可以包含以下属性:</dd>
+ <dd>
+ <dl class="reference-values">
+ <dt><code>allowHttpErrors</code>{{optional_inline}}</dt>
+ <dd>一个 <code>boolean</code>,启用后即使遇到HTTP错误仍然继续下载。 例如,可以使用该标志下载服务错误页面。默认值为<code>false</code>. 当设置为以下值时:
+ <ul>
+ <li><code>false</code>,遇到HTTP错误时下载会被取消。</li>
+ <li><code>true</code>, 即使遇到HTTP错误也会继续下载,并且不会弹出HTTP服务错误报告。但是,如果下载失败的原因是文件相关,网络相关,用户相关,或者说其他错误,仍然会报错。<span style="display: none;"> </span></li>
+ </ul>
+ </dd>
+ <dt><code>body</code>{{optional_inline}}</dt>
+ <dd>一个 <code>string</code>,代表请求的内容。</dd>
+ <dt><code>conflictAction</code>{{optional_inline}}</dt>
+ <dd>一个字符串,表示如果存在命名冲突时你希望进行的操作,字符串内容所代表的类型由 {{WebExtAPIRef('downloads.FilenameConflictAction')}} 定义(未指定时默认为 "uniquify" )。</dd>
+ <dt><code>filename</code>{{optional_inline}}</dt>
+ <dd>一个 <code>string</code> ,表示相对默认保存位置的文件路径——这里提供你希望文件保存的位置,和你想要使用的文件名。绝对路径,空路径,以及包含反向引用的路径 (<code>../</code>) 会导致错误产生。 如果省略,该值将默认为已经提供给下载文件的文件名,并且直接保存到下载文件夹中。</dd>
+ <dt><code>headers</code>{{optional_inline}}</dt>
+ <dd>如果URL使用HTTP或者HTTPS协议, 保存在 <code>array</code> 中的一系列 <code>objects</code> 表示与请求一起发送的额外HTTP请求头。每一个请求头表示为字典对象,包含有关键字 <code>name</code> 还有 <code>value</code>或<code>binaryValue</code>中的一个。 无法指定 <code>XMLHttpRequest</code>和 <code>fetch</code>禁止的请求头,但是 Firefox 70 之后允许使用<code>Referer</code>请求头。尝试使用被禁止的请求头会产生一个错误。</dd>
+ <dt><code>incognito</code>{{optional_inline}}</dt>
+ <dd>一个 <code>boolean</code>:如果被设置为 true,那么这次下载会建立一个隐私浏览会话。 这意味着它只会出现在当前打开的任意隐私窗口的下载管理器。</dd>
+ <dt><code>method</code>{{optional_inline}}</dt>
+ <dd>一个 <code>string</code>,表示<code>url</code>使用HTTP[S] 协议时使用的HTTP方法。其值可能是 "GET" 或 "POST"。</dd>
+ <dt><code>saveAs</code>{{optional_inline}}</dt>
+ <dd>
+ <p>一个<code>boolean</code> 指定是(<code>true</code>)否(<code>false</code>)提供一个文件选择对话框允许用户选择文件名。.</p>
+
+ <p>如果该选项省略, 浏览器会根据用户对于该行为的偏好设置决定是否提供一个文件选择对话框 (在火狐这项设置标签在about:preferences里为"每次都问您要存到哪" ,或者about:config里 <code>browser.download.useDownloadDir</code> )。</p>
+
+ <div class="note">
+ <p><strong>Note</strong>: 如果 <code>saveAs</code> 被设置为 <code>true</code>,Firefox for Android 将会引发一个错误。 当 <code>saveAs</code> 为 <code>false</code> 或空时这个参数会被忽略.</p>
+ </div>
+ </dd>
+ <dt><code>url</code></dt>
+ <dd>一个 <code>string</code>,表示需要下载的链接地址。</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h3 id="返回值">返回值</h3>
+
+<p>一个 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>. 如果成功开始下载,promise会被新创建的{{WebExtAPIRef("downloads.DownloadItem")}} 的 <code>id</code> 填充。否则 promise 会被拒绝并产生一条{{WebExtAPIRef("downloads.InterruptReason")}}错误信息.</p>
+
+<p>如果你使用 <a href="/en-US/docs/Web/API/URL/createObjectURL">URL.createObjectURL()</a> 下载由 JavaScript 创建的数据并且之后想要(使用 <a href="/en-US/docs/Web/API/URL/revokeObjectURL">revokeObjectURL</a>)撤销对象链接(并且强烈推荐这么做),你必须在下载完成后再这么做。监听 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/downloads/onChanged">downloads.onChanged</a> 事件来判断是否下载完成。</p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.downloads.download")}}</p>
+
+<h2 id="例子">例子</h2>
+
+<p>下面这段代码尝试下载一个example文件,同时指定文件名和保存位置,还有 <code>uniquify</code> <code>conflictAction</code> 选项。</p>
+
+<pre class="brush: js">function onStartedDownload(id) {
+ console.log(`Started downloading: ${id}`);
+}
+
+function onFailed(error) {
+ console.log(`Download failed: ${error}`);
+}
+
+var downloadUrl = "https://example.org/image.png";
+
+var downloading = browser.downloads.download({
+ url : downloadUrl,
+ filename : 'my-image-again.png',
+ conflictAction : 'uniquify'
+});
+
+downloading.then(onStartedDownload, onFailed);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>这个 API 基于 Chromium的 <a href="https://developer.chrome.com/extensions/downloads#method-download"><code>chrome.downloads</code></a> API.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/downloads/downloaditem/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/downloads/downloaditem/index.html
new file mode 100644
index 0000000000..ce523d15af
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/downloads/downloaditem/index.html
@@ -0,0 +1,101 @@
+---
+title: downloads.DownloadItem
+slug: Mozilla/Add-ons/WebExtensions/API/downloads/DownloadItem
+translation_of: Mozilla/Add-ons/WebExtensions/API/downloads/DownloadItem
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>{{WebExtAPIRef("downloads")}} API 的 <code>DownloadItem</code> 类代表了一个被下载的文件。</p>
+
+<h2 id="Type">Type</h2>
+
+<p>这个类型的值是对象,包含了以下属性:</p>
+
+<dl class="reference-values">
+ <dt><code>byExtensionId</code>{{optional_inline}}</dt>
+ <dd>一个代表了触发此下载的扩展的 ID 的 <code>string</code> (如果是被扩展触发的话)。一旦设置,不会改变。如果下载不是由扩展触发的,则为 undefined。</dd>
+ <dt><code>byExtensionName</code>{{optional_inline}}</dt>
+ <dd>一个代表了触发此下载的扩展的名字的 <code>string</code> (如果是被扩展触发的话)。如果用户改变了扩展的语言环境,则这个属性的值也可能变化。如果下载不是由扩展触发的,则为 undefined。</dd>
+ <dt><code>bytesReceived</code></dt>
+ <dd>一个代表了在下载过程中从主机接收到的字节数的 <code>number</code> ;不考虑文件压缩。</dd>
+ <dt><code>canResume</code></dt>
+ <dd>一个标识当前中断(例如暂停)的下载是否可以从当前位置恢复的 <code>boolean</code>。</dd>
+ <dt><code>danger</code></dt>
+ <dd>一个标识这个下载是否通过一个不安全的或已知的可疑的站点。可能被设置为 {{WebExtAPIRef('downloads.DangerType')}} 类型。</dd>
+ <dt><code>endTime</code>{{optional_inline}}</dt>
+ <dd>A <code>string</code> (in <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a> format) representing the number of milliseconds between the UNIX epoch and when this download ended. This is undefined if the download has not yet finished.</dd>
+ <dt><code>error</code>{{optional_inline}}</dt>
+ <dd>A string indicating why a download was interrupted. Possible values are defined in the {{WebExtAPIRef('downloads.InterruptReason')}} type. This is undefined if an error has not occurred.</dd>
+ <dt><code>estimatedEndTime</code>{{optional_inline}}</dt>
+ <dd>A <code>string</code> (in <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a> format) representing the estimated number of milliseconds between the UNIX epoch and when this download is estimated to be completed. This is undefined if it is not known (in particular, it is undefined in the <code>DownloadItem</code> that's passed into {{WebExtAPIRef("downloads.onCreated")}}).</dd>
+ <dt><code>exists</code></dt>
+ <dd>A <code>boolean</code> indicating whether a downloaded file still exists (<code>true</code>) or not (<code>false</code>). This information might be out-of-date, as browsers do not automatically watch for file removal — to check whether a file exists, call the {{WebExtAPIRef('downloads.search()')}} method, filtering for the file in question.</dd>
+ <dt><code>filename</code></dt>
+ <dd>A <code>string</code> representing the file's absolute local path.</dd>
+ <dt><code>fileSize</code></dt>
+ <dd>A <code>number</code> indicating the total number of bytes in the whole file, after decompression. A value of -1 here means that the total file size is unknown.</dd>
+ <dt><code>id</code></dt>
+ <dd>An <code>integer</code> representing a unique identifier for the downloaded file that is persistent across browser sessions.</dd>
+ <dt><code>incognito</code></dt>
+ <dd>A <code>boolean</code> that indicates whether the download is recorded in the browser's history (<code>false</code>), or not (<code>true</code>).</dd>
+ <dt><code>mime</code></dt>
+ <dd>A <code>string</code> representing the downloaded file's MIME type.</dd>
+ <dt><code>paused</code></dt>
+ <dd>A <code>boolean</code> indicating whether the download is paused, i.e. if the download has stopped reading data from the host but has kept the connection open. If so, the value is <code>true</code>, <code>false</code> if not.</dd>
+ <dt><code>referrer</code></dt>
+ <dd>A <code>string</code> representing the downloaded file's referrer.</dd>
+ <dt><code>startTime</code></dt>
+ <dd>A <code>string</code> (in <a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a> format) representing the number of milliseconds between the UNIX epoch and when this download began.</dd>
+ <dt><code>state</code></dt>
+ <dd>A <code>string</code> Indicating whether the download is progressing, interrupted, or complete. Possible values are defined in the {{WebExtAPIRef('downloads.State')}} type.</dd>
+ <dt><code>totalBytes</code></dt>
+ <dd>A <code>number</code> indicating the total number of bytes in the file being downloaded. This does not take file compression into consideration. A value of -1 here means that the total number of bytes is unknown.</dd>
+ <dt><code>url</code></dt>
+ <dd>A <code>string</code> representing the absolute URL from which the file was downloaded.</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.downloads.DownloadItem")}}</p>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/downloads#type-DownloadItem"><code>chrome.downloads</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/downloads/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/downloads/index.html
new file mode 100644
index 0000000000..a2074471b7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/downloads/index.html
@@ -0,0 +1,134 @@
+---
+title: downloads
+slug: Mozilla/Add-ons/WebExtensions/API/downloads
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - Interface
+ - NeedsTranslation
+ - Non-standard
+ - Reference
+ - TopicStub
+ - WebExtensions
+ - downloads
+translation_of: Mozilla/Add-ons/WebExtensions/API/downloads
+---
+<div>{{AddonSidebar}}</div>
+
+<div>启用与浏览器的下载管理器交互的扩展。你可以使用这个 API 模块来下载文件、取消、暂停、恢复下载和在文件管理器中显示下载的文件。</div>
+
+<p>为使用此 API,你需要在你的 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> 文件中声明 "downloads" <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">API 权限</a>。</p>
+
+<h2 id="Types">Types</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("downloads.FilenameConflictAction")}}</dt>
+ <dd>定义当一个下载的文件与现存的文件命名冲突时要做什么。</dd>
+ <dt>{{WebExtAPIRef("downloads.InterruptReason")}}</dt>
+ <dd>定义一系列中断下载的可能理由。</dd>
+ <dt>{{WebExtAPIRef("downloads.DangerType")}}</dt>
+ <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">定义一组与可下载文件相关的潜在危险的常见警告。</span></span></dd>
+ <dt>{{WebExtAPIRef("downloads.State")}}</dt>
+ <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">定义当前下载可能处于的不同状态。</span></span></dd>
+ <dt>{{WebExtAPIRef("downloads.DownloadItem")}}</dt>
+ <dd>代表下载的文件。</dd>
+ <dt>{{WebExtAPIRef("downloads.StringDelta")}}</dt>
+ <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">表示两个字符串之间的差异。</span></span></dd>
+ <dt>{{WebExtAPIRef("downloads.DoubleDelta")}}</dt>
+ <dd>代表两个双精度浮点数之间的差异。</dd>
+ <dt>{{WebExtAPIRef("downloads.BooleanDelta")}}</dt>
+ <dd>代表两个布尔数之间的差异。</dd>
+ <dt>{{WebExtAPIRef("downloads.DownloadTime")}}</dt>
+ <dd>代表一个下载将会花费的时间。</dd>
+ <dt>{{WebExtAPIRef("downloads.DownloadQuery")}}</dt>
+ <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">定义一组参数,可用于在下载管理器中搜索一组特定的下载。</span></span></dd>
+</dl>
+
+<h2 id="Functions">Functions</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("downloads.download()")}}</dt>
+ <dd>下载一个文件,给出它的 URL 和其他可选的参数。</dd>
+ <dt>{{WebExtAPIRef("downloads.search()")}}</dt>
+ <dd>查询 {{WebExtAPIRef("downloads.DownloadItem", "DownloadItems")}} 是否在浏览器的下载管理器中可用,返回匹配指定的搜索标准的条目。</dd>
+ <dt>{{WebExtAPIRef("downloads.pause()")}}</dt>
+ <dd>暂停一个下载。</dd>
+ <dt>{{WebExtAPIRef("downloads.resume()")}}</dt>
+ <dd>恢复一个暂停的下载。</dd>
+ <dt>{{WebExtAPIRef("downloads.cancel()")}}</dt>
+ <dd>取消一个下载。</dd>
+ <dt>{{WebExtAPIRef("downloads.getFileIcon()")}}</dt>
+ <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">检索指定下载的图标。</span></span></dd>
+ <dt>{{WebExtAPIRef("downloads.open()")}}</dt>
+ <dd>用下载的文件相关联的程序打开它。</dd>
+ <dt>{{WebExtAPIRef("downloads.show()")}}</dt>
+ <dd>打开当前平台的文件管理应用来在它包含的文件夹中显示下载的文件。</dd>
+ <dt>{{WebExtAPIRef("downloads.showDefaultFolder()")}}</dt>
+ <dd>用当前平台的文件管理应用显示默认下载文件夹。</dd>
+ <dt>{{WebExtAPIRef("downloads.erase()")}}</dt>
+ <dd>擦除浏览器的下载历史中匹配 {{WebExtAPIRef("downloads.DownloadItem", "DownloadItems")}} 的下载记录,不会在磁盘中删除文件。</dd>
+ <dt>{{WebExtAPIRef("downloads.removeFile()")}}</dt>
+ <dd>从磁盘中移除下载的文件,但不从浏览器的下载历史中去除。</dd>
+ <dt>{{WebExtAPIRef("downloads.acceptDanger()")}}</dt>
+ <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">提示用户接受或取消危险的下载。</span></span></dd>
+ <dt>{{WebExtAPIRef("downloads.drag()")}}</dt>
+ <dd>   <span class="tlid-translation translation" lang="zh-CN"><span title="">将下载的文件拖动到另一个应用程序。</span></span></dd>
+ <dt>{{WebExtAPIRef("downloads.setShelfEnabled()")}}</dt>
+ <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">启用或禁用与当前浏览器配置文件关联的每个窗口底部的灰色架子。</span> <span title="">只要至少一个扩展名已禁用该架子,它就会被禁用。</span></span></dd>
+</dl>
+
+<h2 id="Events">Events</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("downloads.onCreated")}}</dt>
+ <dd>当一个下载开始时被 {{WebExtAPIRef("downloads.DownloadItem", "DownloadItem")}} 对象触发。</dd>
+ <dt>{{WebExtAPIRef("downloads.onErased")}}</dt>
+ <dd>当一个下载从历史中擦除时被 Fires with the <code>downloadId</code> 触发。</dd>
+ <dt>{{WebExtAPIRef("downloads.onChanged")}}</dt>
+ <dd>当任意一个 {{WebExtAPIRef("downloads.DownloadItem", "DownloadItem")}} 的属性期望 <code>bytesReceived</code> 改变时,此事件被这个 `downloadId` 和包含了变化属性的对象触发。</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.downloads")}}</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/downloads"><code>chrome.downloads</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/find/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/find/index.html
new file mode 100644
index 0000000000..cda583e456
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/find/index.html
@@ -0,0 +1,25 @@
+---
+title: find
+slug: Mozilla/Add-ons/WebExtensions/API/find
+translation_of: Mozilla/Add-ons/WebExtensions/API/find
+---
+<div><font><font>{{AddonSidebar}}</font></font></div>
+
+<p><font><font>在网页中查找文本,并突出显示匹配项。</font></font></p>
+
+<p><font><font>要使用此API,您需要具有“查找” </font></font><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions"><font><font>权限</font></font></a><font><font>。</font></font></p>
+
+<h2 id="功能"><font><font>功能</font></font></h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("find.find()")}}</dt>
+ <dd><font><font>在网页中查找文本。</font></font></dd>
+ <dt>{{WebExtAPIRef("find.highlightResults()")}}</dt>
+ <dd><font><font>突出显示找到的最后一组匹配项。</font></font></dd>
+ <dt>{{WebExtAPIRef("find.removeHighlighting()")}}</dt>
+ <dd><font><font>删除所有突出显示。</font></font></dd>
+</dl>
+
+<h2 id="浏览器兼容性"><font><font>浏览器兼容性</font></font></h2>
+
+<p>{{Compat("webextensions.api.find", 1, 1)}} {{WebExtExamples("h2")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/history/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/history/index.html
new file mode 100644
index 0000000000..7412530cb6
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/history/index.html
@@ -0,0 +1,134 @@
+---
+title: history
+slug: Mozilla/Add-ons/WebExtensions/API/history
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - History
+ - Interface
+ - NeedsTranslation
+ - Non-standard
+ - Reference
+ - TopicStub
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/API/history
+---
+<div>{{AddonSidebar}}</div>
+
+<p>使用 <code>history</code> API与浏览器历史记录进行交互。</p>
+
+<div class="note">
+<p>注意:下载也被当做一个 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/history/HistoryItem" title="A HistoryItem object provides information about a page in the browser history."><code>HistoryItem</code></a> 对象。因此,<code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/history/onVisited" title="Fired each time the user visits a page. A history.HistoryItem object is passed to the listener. This event fires before the page has loaded.">history.onVisited</a></code>等事件也会被下载所触发。</p>
+</div>
+
+<p>浏览器历史记录是对用户所访问的页面按时间顺序进行的记录和保存。history API 可以帮你实现以下功能:</p>
+
+<ul>
+ <li><a href="/en-US/Add-ons/WebExtensions/API/history/search">查找浏览器历史记录中出现过的页面</a></li>
+ <li><a href="/en-US/Add-ons/WebExtensions/API/history/deleteUrl">移除浏览器历史记录中的单个页面</a></li>
+ <li><a href="/en-US/Add-ons/WebExtensions/API/history/addUrl">向浏览器历史记录中添加页面</a></li>
+ <li><a href="/en-US/Add-ons/WebExtensions/API/history/deleteAll">移除所有浏览器历史记录中的页面</a></li>
+</ul>
+
+<p>然而,用户可能多次访问单个页面,因此API中有访问集合“visits”的概念。所以,该API还可以做如下使用:</p>
+
+<ul>
+ <li><a href="/en-US/Add-ons/WebExtensions/API/history/getVisits">获取用户对单个页面的所有访问记录的集合</a></li>
+ <li><a href="/en-US/Add-ons/WebExtensions/API/history/deleteRange">移除给定期间内任意页面的访问记录的集合</a></li>
+</ul>
+
+<p>使用该API之前,扩展程序必须在其 <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a></code> 文件中获取history的<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">许可</a>。</p>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("history.TransitionType")}}</dt>
+ <dd>描述浏览器如何转到特定页面。</dd>
+ <dt>{{WebExtAPIRef("history.HistoryItem")}}</dt>
+ <dd>
+ <p>提供浏览器历史记录中单个特定页面的详细信息。</p>
+ </dd>
+ <dt>{{WebExtAPIRef("history.VisitItem")}}</dt>
+ <dd>
+ <p>描述对一个页面的单次访问。</p>
+ </dd>
+</dl>
+
+<h2 id="方法">方法</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("history.search()")}}</dt>
+ <dd>在浏览器历史记录中查找符合给定条件的<code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/History/HistoryItem" title="A HistoryItem object provides information about one result from a history query.">history.HistoryItem</a></code></dd>
+ <dt>{{WebExtAPIRef("history.getVisits()")}}</dt>
+ <dd>获取指定页面的访问集信息。</dd>
+ <dt>{{WebExtAPIRef("history.addUrl()")}}</dt>
+ <dd>为浏览器历史记录添加一个指定页面的访问。</dd>
+ <dt>{{WebExtAPIRef("history.deleteUrl()")}}</dt>
+ <dd>移除浏览器历史记录中所有对指定URL的访问。</dd>
+ <dt>{{WebExtAPIRef("history.deleteRange()")}}</dt>
+ <dd>移除指定时间段内对用户指定页面的访问。</dd>
+ <dt>{{WebExtAPIRef("history.deleteAll()")}}</dt>
+ <dd>移除浏览器历史记录中的所有访问。</dd>
+</dl>
+
+<h2 id="事件">事件</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("history.onTitleChanged")}}</dt>
+ <dd>
+ <div>当用户访问的页面标题被记录时触发。</div>
+ </dd>
+ <dt>{{WebExtAPIRef("history.onVisited")}}</dt>
+ <dd>每次用户访问页面时会触发,并提供该页面的 {{WebExtAPIRef("history.HistoryItem")}} 数据。</dd>
+ <dt>{{WebExtAPIRef("history.onVisitRemoved")}}</dt>
+ <dd>
+ <p>当一个URL被彻底从浏览器历史记录中移除时触发。</p>
+ </dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.history")}}</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>致谢</strong>
+
+<p>该 API 基于Chromium的<a href="https://developer.chrome.com/extensions/history"><code>chrome.history</code></a> API。该文档由Chromium代码中的<a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/history.json"><code>history.json</code></a>衍生而来。</p>
+
+<p>微软 Edge 兼容性数据由微软公司提供并包含在如下证书中—— Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/history/ontitlechanged/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/history/ontitlechanged/index.html
new file mode 100644
index 0000000000..bf79b4c6d7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/history/ontitlechanged/index.html
@@ -0,0 +1,111 @@
+---
+title: history.onTitleChanged
+slug: Mozilla/Add-ons/WebExtensions/API/history/onTitleChanged
+tags:
+ - History
+translation_of: Mozilla/Add-ons/WebExtensions/API/history/onTitleChanged
+---
+<div>{{AddonSidebar()}}</div>
+
+<div>当document的标题更改时触发</div>
+
+<div> </div>
+
+<div>你可以使用 {{WebExtAPIRef("history.onVisited")}}去进行监听. However, the {{WebExtAPIRef("history.HistoryItem")}} that this event passes to its listener does not include the page title, because the page title is typically not known at the time <code>history.onVisited</code> is sent.</div>
+
+<div> </div>
+
+<div>Instead, the stored {{WebExtAPIRef("history.HistoryItem")}} is updated with the page title after the page has loaded, once the title is known. The history.onTitleChanged event is fired at that time. So if you need to know the titles of pages as they are visited, listen for <code>history.onTitleChanged</code>.</div>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js">browser.history.onTitleChanged.addListener(listener)
+browser.history.onTitleChanged.removeListener(listener)
+browser.history.onTitleChanged.hasListener(listener)
+</pre>
+
+<p>Events have three functions:</p>
+
+<dl>
+ <dt><code>addListener(listener)</code></dt>
+ <dd>Adds a listener to this event.</dd>
+ <dt><code>removeListener(listener)</code></dt>
+ <dd>Stop listening to this event. The <code>listener</code> argument is the listener to remove.</dd>
+ <dt><code>hasListener(listener)</code></dt>
+ <dd>Check whether <code>listener</code> is registered for this event. Returns <code>true</code> if it is listening, <code>false</code> otherwise.</dd>
+</dl>
+
+<h2 id="addListener_syntax">addListener syntax</h2>
+
+<h3 id="Parameters">Parameters</h3>
+
+<dl>
+ <dt><code>callback</code></dt>
+ <dd>
+ <p>Function that will be called when this event occurs. The function will be passed an object with the following properties:</p>
+
+ <dl class="reference-values">
+ <dt><code>url</code></dt>
+ <dd><code>String</code>. URL of the page visited.</dd>
+ <dt><code>title</code></dt>
+ <dd><code>String</code>. Title of the page visited.</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.history.onTitleChanged")}}</p>
+
+<h2 id="Examples">Examples</h2>
+
+<p>Listen for title change events, and log the URL and title of the visited pages.</p>
+
+<pre class="brush: js">function handleTitleChanged(item) {
+ console.log(item.title);
+ console.log(item.url);
+}
+
+browser.history.onTitleChanged.addListener(handleTitleChanged);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/history#event-onVisited"><code>chrome.history</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/history.json"><code>history.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/i18n/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/i18n/index.html
new file mode 100644
index 0000000000..73897ac0ea
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/i18n/index.html
@@ -0,0 +1,85 @@
+---
+title: i18n
+slug: Mozilla/Add-ons/WebExtensions/API/i18n
+translation_of: Mozilla/Add-ons/WebExtensions/API/i18n
+---
+<div>{{AddonSidebar}}</div>
+
+<p>国际化扩展的函数。您可以使用这些 api 从与扩展打包在一起的本地化文件中获取本地化字符串,查找浏览器的当前语言,并查找其 <a href="/zh-CN/docs/Web/HTTP/Content_negotiation#The_Accept-Language_header">Accept-Language header</a>头的值。</p>
+
+<p id="See_also">有关对扩展使用 i18n 的详细信息,请参阅:</p>
+
+<ul>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Internationalization">Internationalization</a>国际化: 使用 WebExtension i18n 系统的指南</li>
+ <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n/Locale-Specific_Message_reference">Locale-Specific Message reference</a>: 扩展在 <code>messages.json</code>文件中提供特定于语言环境的字符串。 <font>此网页介绍</font><code>messages.json</code></li>
+</ul>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("i18n.LanguageCode")}}</dt>
+ <dd>一个<a href="https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.10">语言标记</a> 例如 <code>"en-US"</code> 或者 "<code>fr</code>".</dd>
+</dl>
+
+<h2 id="方法">方法</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("i18n.getAcceptLanguages()")}}</dt>
+ <dd>得到浏览器 <a href="/en-US/docs/Web/HTTP/Content_negotiation#The_Accept-Language_header">支持的语言</a> 。这与浏览器使用的区域设置不同。要获得区域设置,请使用{{WebExtAPIRef('i18n.getUILanguage')}}.</dd>
+ <dt>{{WebExtAPIRef("i18n.getMessage()")}}</dt>
+ <dd>获取指定消息的本地化字符串。</dd>
+ <dt>{{WebExtAPIRef("i18n.getUILanguage()")}}</dt>
+ <dd>获取浏览器的用户界面语言。 这与返回首选的用户语言 {{WebExtAPIRef('i18n.getAcceptLanguages')}} 不同。</dd>
+ <dt>{{WebExtAPIRef("i18n.detectLanguage()")}}</dt>
+ <dd>使用 <a href="https://github.com/CLD2Owners/cld2">Compact Language Detector</a>属性检测所提供文本的语言。</dd>
+</dl>
+
+<dl>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.i18n")}}</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<dl>
+</dl>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>这个 API 是基于 Chromium 的 <a href="https://developer.chrome.com/extensions/i18n"><code>chrome.i18n</code></a> API,这个文档源自 Chromium 代码中的  <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/i18n.json"><code>history.json</code></a> 。</p>
+
+<p>微软 Edge 的兼容性数据由微软公司提供,并在这里收录在《知识共享3.0美国许可证》中。</p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate">// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/idle/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/idle/index.html
new file mode 100644
index 0000000000..a6160bc90d
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/idle/index.html
@@ -0,0 +1,97 @@
+---
+title: idle
+slug: Mozilla/Add-ons/WebExtensions/API/idle
+tags:
+ - API
+ - Idle
+ - WebExtensions
+ - requestIdleCallback
+ - 性能优化
+translation_of: Mozilla/Add-ons/WebExtensions/API/idle
+---
+<div>{{AddonSidebar}}</div>
+
+<p>找出用户系统何时处于空闲,锁定或活动状态。</p>
+
+<p>要使用此API,您需要具有“空闲”<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a>。</p>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("idle.IdleState")}}</dt>
+ <dd>
+ <p>描述设备空闲状态的字符串。</p>
+ </dd>
+</dl>
+
+<h2 id="函数">函数</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("idle.queryState()")}}</dt>
+ <dd>如果系统被锁定则返回“已锁定”,如果用户未在指定的秒数内生成任何输入,则返回“空闲”,否则返回“活动”。</dd>
+ <dt>{{WebExtAPIRef("idle.setDetectionInterval()")}}</dt>
+ <dd>设置用于确定系统何时处于 {{WebExtAPIRef("idle.onStateChanged")}}  事件的空闲状态的时间间隔。</dd>
+</dl>
+
+<h2 id="事件">事件</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("idle.onStateChanged")}}</dt>
+ <dd>当系统改变状态时触发。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.idle")}}</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>确认</strong>
+
+<p>此 API基于 Chromium 的 <a href="https://developer.chrome.com/extensions/idle"><code>chrome.idle</code></a> API。本文档源自 Chromium代码中的 <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/idle.json"><code>idle.json</code></a> 。</p>
+
+<p>Microsoft Edge 兼容性数据由 Microsoft Corporation提供,并包含在Creative Commons Attribution 3.0 United States License下。</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
+
+<div></div>
+
+<h3 id="了解更多">了解更多:</h3>
+
+<div><a href="https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback">https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestIdleCallback </a></div>
+
+<div></div>
+
+<div></div>
+
+<div>...</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/index.html
new file mode 100644
index 0000000000..a469192447
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/index.html
@@ -0,0 +1,50 @@
+---
+title: API
+slug: Mozilla/Add-ons/WebExtensions/API
+tags:
+ - NeedsTranslation
+ - TopicStub
+translation_of: Mozilla/Add-ons/WebExtensions/API
+---
+<div>{{AddonSidebar}}</div>
+
+<div>
+<p>WebExtension JavaScript API 可以在附加组件的<a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts">后台脚本</a>和附加组件定义的任何<a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/User_interface_components#Browser_actions">浏览器动作</a>或<a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/User_interface_components#Page_actions">页面动作</a>中使用。这里的部分API也可以通过附加组件的<a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Content_scripts">内容脚本</a>访问(见<a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/Content_scripts#WebExtension_APIs">内容脚本指南列表</a>)。</p>
+
+<p>要使用更强大的 API,您需要在您的 manifest.json 中<a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/manifest.json/permissions">申请权限</a>。</p>
+
+<p>您可以使用 <code>browser</code> 命名空间访问这些 API。</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js">function logTabs(tabs) {
+ console.log(tabs);
+}
+
+browser.tabs.query({currentWindow: true}, logTabs);</code></pre>
+</div>
+
+<div>
+<p>许多 API 为异步,返回一个 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js">function logCookie(c) {
+ console.log(c);
+}
+
+function logError(e) {
+ console.error(e);
+}
+
+var setCookie = browser.cookies.set(
+ {url: "https://developer.mozilla.org/"}
+);
+setCookie.then(logCookie, logError);</code></pre>
+</div>
+
+<div>
+<p>请注意,这不同于 Google Chrome 的扩展系统,它使用 <code>chrome</code> 而非 <code>browser</code> 名字空间,并且对异步函数使用回调而不是 promises。为辅助移植,Firefox 实现的 WebExtensions 支持 <code>chrome</code> 和回调以及 <code>browser</code> 和 promises。Mozilla 也写了一个 polyfill 使使用 <code>browser</code> 和 promises 的代码能不经修改的在 Chrome 中使用:<a class="external external-icon" href="https://github.com/mozilla/webextension-polyfill">https://github.com/mozilla/webextension-polyfill</a>。</p>
+
+<p>微软 Edge 使用 <code>browser</code> 名字空间,但尚不支持基于 promise 的异步API。目前在 Edge 中,异步 API 必须使用回调。</p>
+
+<p>并非所有浏览器都支持这里的所有 API:详情见<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs">浏览器对 JavaScript API 的支持</a>。</p>
+</div>
+
+<div>{{SubpagesWithSummaries}}</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/permissions/contains/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/permissions/contains/index.html
new file mode 100644
index 0000000000..c701942058
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/permissions/contains/index.html
@@ -0,0 +1,94 @@
+---
+title: permissions.contains()
+slug: Mozilla/Add-ons/WebExtensions/API/permissions/contains
+tags:
+ - Contains
+ - permissions.contains()
+translation_of: Mozilla/Add-ons/WebExtensions/API/permissions/contains
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>检查扩展名是否具有给定 {{WebExtAPIRef("permissions.Permissions")}}  对象中列出的权限。</p>
+
+<p>The <code>Permissions</code> argument may contain either an origins property, which is an array of <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">host permissions</a>, or a <code>permissions</code> property, which is an array of <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">API permissions</a>, or both.</p>
+
+<p>This is an asynchronous function that returns a <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>. The promise is fulfilled with true only if all the extension currently has all the given permissions. For host permissions, if the extension's permissions <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns">pattern-match</a> the permissions listed in <code>origins</code>, then they are considered to match.</p>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js notranslate">var getContains = browser.permissions.contains(
+ permissions // Permissions object
+)
+</pre>
+
+<h3 id="Parameters">Parameters</h3>
+
+<dl>
+ <dt><code>permissions</code></dt>
+ <dd>A {{WebExtAPIRef("permissions.Permissions")}} object.</dd>
+</dl>
+
+<h3 id="Return_value">Return value</h3>
+
+<p>A <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> that will be fulfilled with <code>true</code> if the extension already has all the permissions listed in the <code>permissions</code> argument, or <code>false</code> otherwise.</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.permissions.contains")}}</p>
+
+<h2 id="Examples">Examples</h2>
+
+<pre class="brush: js notranslate">// Extension permissions are:
+// "webRequest", "tabs", "*://*.mozilla.org/*"
+
+var testPermissions1 = {
+ origins: ["*://mozilla.org/"],
+ permissions: ["tabs"]
+};
+
+browser.permissions.contains(testPermissions1).then((result) =&gt; {
+ console.log(result); // true
+});
+
+var testPermissions2 = {
+  origins: ["*://mozilla.org/"],
+  permissions: ["tabs", "alarms"]
+};
+
+browser.permissions.contains(testPermissions2).then((result) =&gt; {
+ console.log(result); // false, "alarms" doesn't match
+});
+
+var testPermissions3 = {
+  origins: ["https://developer.mozilla.org/"],
+  permissions: ["tabs", "webRequest"]
+};
+
+browser.permissions.contains(testPermissions3).then((result) =&gt; {
+ console.log(result); // true: "https://developer.mozilla.org/"
+}); // matches: "*://*.mozilla.org/*"
+
+var testPermissions4 = {
+  origins: ["https://example.org/"]
+};
+
+browser.permissions.contains(testPermissions4).then((result) =&gt; {
+ console.log(result); // false, "https://example.org/"
+}); // does not match
+
+</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/permissions"><code>chrome.permissions</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div id="gtx-trans" style="position: absolute; left: 677px; top: 46px;">
+<div class="gtx-trans-icon"></div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/permissions/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/permissions/index.html
new file mode 100644
index 0000000000..df6c1c8e5c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/permissions/index.html
@@ -0,0 +1,93 @@
+---
+title: permissions
+slug: Mozilla/Add-ons/WebExtensions/API/permissions
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - NeedsTranslation
+ - Permissions
+ - Reference
+ - TopicStub
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/API/permissions
+---
+<div>{{AddonSidebar}}</div>
+
+<div>Enables extensions to request extra permissions at runtime, after they have been installed.</div>
+
+<div></div>
+
+<p>Extensions need permissions to access more powerful WebExtension APIs. They can ask for permissions at install time, by including the permissions they need in the <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code> manifest.json key. The main advantages of asking for permissions at install time are:</p>
+
+<ul>
+ <li>The user is only asked once, so it's less disruptive for them, and a simpler decision.</li>
+ <li>The extension can rely on the access to the APIs it needs, because if already running, the permissions have been granted.</li>
+</ul>
+
+<p>There is not yet a simple GUI, for users to view permissions of their installed WebExtension Add-ons.  Users must use about:debugging, go to the Add-ons section, then use the "Manifest Url" link for this Add-on. This shows raw json, which includes a "permissions" block, showing the permissions used by this addon.</p>
+
+<p>With the permissions API, an extension can ask for additional permissions at runtime. These permissions need to be listed in the <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/optional_permissions">optional_permissions</a></code> manifest.json key. Note that some permissions are not allowed in <code>optional_permissions</code>. The main advantages of this are:</p>
+
+<ul>
+ <li>The extension can run with a smaller set of permissions, except when it actually needs them.</li>
+ <li>The extension can handle permission denial in a graceful manner, instead of presenting the user with a global "all or nothing" choice at install time. You can still get a lot out of that map extension, without giving it access to your location, for example.</li>
+ <li>
+ <p>The extension may need <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">host permissions</a>, but not know at install time which host permissions it needs. For example, the list of hosts may be a user setting. In this scenario, asking for a more specific range of hosts at runtime, can be an alternative to asking for "&lt;all_urls&gt;" at install time.</p>
+ </li>
+</ul>
+
+<div>To use the permissions API, decide which permissions your extension can request at runtime, and list them in <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/optional_permissions">optional_permissions</a></code>. After this, you can request any permissions that were included in <code>optional_permissions</code>. Requests may only be made in the handler for a user action (for example, a click handler).</div>
+
+<div></div>
+
+<div>For advice on designing your request for runtime permissions, to maximize the likelihood that users grant them, see <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Request_the_right_permissions#Request_permissions_at_runtime">Request permissions at runtime</a>.</div>
+
+<h2 id="Types">Types</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("permissions.Permissions")}}</dt>
+ <dd>Represents a set of permissions.</dd>
+</dl>
+
+<h2 id="Methods">Methods</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("permissions.contains()")}}</dt>
+ <dd>Discover an extension's given set of permissions.</dd>
+ <dt>{{WebExtAPIRef("permissions.getAll()")}}</dt>
+ <dd>Get all the permissions this extension currently has.</dd>
+ <dt>{{WebExtAPIRef("permissions.remove()")}}</dt>
+ <dd>Give up a set of permissions.</dd>
+ <dt>{{WebExtAPIRef("permissions.request()")}}</dt>
+ <dd>Ask for a set of permissions.</dd>
+</dl>
+
+<h2 id="Event_handlers">Event handlers</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("permissions.onAdded")}}</dt>
+ <dd>Fired when a new permission is granted.</dd>
+ <dt>{{WebExtAPIRef("permissions.onRemoved")}}</dt>
+ <dd>Fired when a permission is removed.</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.permissions")}}</p>
+
+<h2 id="See_also">See also</h2>
+
+<ul>
+ <li><code>manifest.json</code> <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code> property</li>
+ <li><code>manifest.json</code> <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/optional_permissions">optional_permissions</a></code> property</li>
+</ul>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/permissions"><code>chrome.permissions</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/proxy/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/proxy/index.html
new file mode 100644
index 0000000000..e259cf65fc
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/proxy/index.html
@@ -0,0 +1,65 @@
+---
+title: proxy
+slug: Mozilla/Add-ons/WebExtensions/API/proxy
+translation_of: Mozilla/Add-ons/WebExtensions/API/proxy
+---
+<div>{{AddonSidebar}}</div>
+
+<div></div>
+
+<div class="blockIndicator warning">
+<p><strong>Warning</strong><br>
+ 不推荐使用 {{WebExtAPIRef("proxy.register()")}} 或者 {{WebExtAPIRef("proxy.unregister()")}} 方法使用 <a href="/en-US/Add-ons/WebExtensions/API/proxy/register#PAC_file_specification">Proxy Auto-Configuration (PAC) file</a>. 这个 API 将会在 Firefox 68 中废弃并且在 Firefox 71中删除.</p>
+</div>
+
+<p>使用proxy API来代理web请求。你可以使用<code><strong>{{WebExtAPIRef("proxy.onRequest")}}</strong></code>事件监听器来拦截web请求,并且返回一个可以描述是否代理并且怎样代理它们的对象。</p>
+
+<p>{{WebExtAPIRef("proxy.onRequest")}}的好处在于,用于实现你拦截策略的代码在你的扩展的后台脚本运行,所以,它可以让<code><strong>WebExtension APIs</strong></code>能够完全的访问你的扩展(举例来说,可以访问你扩展的<code>storage</code>和像dns等类似的网络api)</p>
+
+<p>除了这个api,扩展也能够使用<strong><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserSettings/proxyConfig">browserSettings.proxyConfig</a></code></strong>属性来重新编辑你全局的<code>proxy</code>设置</p>
+
+<p>Chrome浏览器提供了一个叫做<code><a href="https://developer.chrome.com/extensions/proxy">'proxy'</a>的</code>api扩展,它的功能跟这个api类似,在chrome的api中也可以用来实现一个<code>拦截策略。</code>然而,Chrome 的API的设计跟这个API设计完全不同。因为这个API跟谷歌的<code>proxy</code>的<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">API完全不同, 这个API只能通过'browser'命名空间访问</span></font></p>
+
+<p>如果你想用这个API你需要得到'<code>proxy</code>'的<a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>.并且,如果你想拦截一个请求,你同样也需要当前拦截请求的url的 <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">host permission</a>。</p>
+
+<h2 id="Types">Types</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("proxy.ProxyInfo")}}</dt>
+ <dd>Describes a proxy.</dd>
+ <dt>{{WebExtAPIRef("proxy.RequestDetails")}}</dt>
+ <dd>
+ <p>Contains information about a web request that the browser is about to make.</p>
+ </dd>
+</dl>
+
+<h2 id="Properties">Properties</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("proxy.settings")}}</dt>
+ <dd>Get and set proxy settings.</dd>
+</dl>
+
+<h2 id="Functions">Functions</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("proxy.register()")}} {{Deprecated_Inline}}</dt>
+ <dd>Registers the given proxy script.</dd>
+ <dt>{{WebExtAPIRef("proxy.unregister()")}} {{Deprecated_Inline}}</dt>
+ <dd>Unregisters the proxy script.</dd>
+</dl>
+
+<h2 id="Events">Events</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("proxy.onError")}}</dt>
+ <dd>Fired when the system encounters an error running the PAC script or the <code>onRequest</code> listener.</dd>
+ <dt>{{WebExtAPIRef("proxy.onRequest")}}</dt>
+ <dd>Fired when a web request is about to be made, giving the extension an opportunity to proxy it.</dd>
+</dl>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.proxy")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/connectnative/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/connectnative/index.html
new file mode 100644
index 0000000000..d3d4d9a14d
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/connectnative/index.html
@@ -0,0 +1,114 @@
+---
+title: 连接本地应用程序方法 - runtime.connectNative()
+slug: Mozilla/Add-ons/WebExtensions/API/runtime/connectNative
+tags:
+ - 附加组件连接本地应用程序
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/connectNative
+---
+<div>{{AddonSidebar()}}</div>
+
+<div>该方法能够把附加组件和用户计算机上的一个本地应用程序相连接.</div>
+
+<div> </div>
+
+<div>同时我们需要本地应用程序的名称作为参数. 当启动本地应用程序的时候会返回一个{{WebExtAPIRef("runtime.Port")}} 对象给调用者.</div>
+
+<div> </div>
+
+<div>之后可以通过该对象的 Port.onMessage() 和 Port.postMessage()方法来和本地应用程序进行信息交互.</div>
+
+<div> </div>
+
+<div>本地应用程序会一直运行直到退出, 除非调用了 <code>Port.disconnect()</code>方法, 亦或创建该Port对象的页面被摧毁了. 一旦Port对象断开连接, 浏览器会给该进程几秒的时间以便安全优雅的退出和释放, 之后如果发现该进程没退出的话就直接暴力干掉.</div>
+
+<div> </div>
+
+<p>更多信息, 请查看 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging">Native messaging</a>.</p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">var port = browser.runtime.connectNative(
+ application // 这是一个字符串
+)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>application</code></dt>
+ <dd><code>值类型为string</code>. 该参数的值为要连接的本地应用程序的名称. 必须要跟 <a href="/en-US/Add-ons/WebExtensions/Native_messaging#App_manifest">native application's manifest file</a> 中的"name"特性的值一致.</dd>
+</dl>
+
+<h3 id="返回值">返回值</h3>
+
+<p>是一个 {{WebExtAPIRef('runtime.Port')}} 对象. 该对象是用来跟本地应用程序进行消息交互的.</p>
+
+<h2 id="浏览器的兼容性">浏览器的兼容性</h2>
+
+<p class="hidden">本页中的兼容性表格是通过结构化后的数据生成的. 如果你想提供更多的兼容性数据, 请检出 <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 添加修改后再给我们发送一个pull请求.</p>
+
+<p>{{Compat("webextensions.api.runtime.connectNative")}}</p>
+
+<h2 id="示例">示例</h2>
+
+<p>本示例中连接了本地应用程序"ping_pong"并且启动了监听以便接收消息. 当用户单击浏览器上的操作按钮时它会发送一个本地应用程序的消息:</p>
+
+<pre class="brush: js">/*
+启动时, 连接"ping_pong"本地应用程序.
+*/
+var port = <code class="language-js">browser</code>.runtime.connectNative("ping_pong");
+
+/*
+监听(接收)来自"ping_pong"本地应用程序的消息.
+*/
+port.onMessage.addListener((response) =&gt; {
+ console.log("Received: " + response);
+});
+
+/*
+当浏览器上的单击操作被触发时, 发送一个消息给本地应用程序.
+*/
+<code class="language-js">browser</code>.browserAction.onClicked.addListener(() =&gt; {
+ console.log("Sending: ping");
+ port.postMessage("ping");
+});</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>万分感谢</strong>
+
+<p>该 API 是基于 Chromium 的 <a href="https://developer.chrome.com/extensions/runtime#method-connectNative"><code>chrome.runtime</code></a> API. 本文档采自 Chromium 代码中的 <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a>.</p>
+
+<p>Microsoft Edge 的兼容性数据由微软公司提供, 并被列入以下许可证 Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/getmanifest/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/getmanifest/index.html
new file mode 100644
index 0000000000..77870d7010
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/getmanifest/index.html
@@ -0,0 +1,79 @@
+---
+title: 读取主文件信息方法 - runtime.getManifest()
+slug: Mozilla/Add-ons/WebExtensions/API/runtime/getManifest
+tags:
+ - 读取主文件信息方法
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/getManifest
+---
+<div>{{AddonSidebar()}}</div>
+
+<div>该方法会获取一个完整的主文件 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json </a>, 并返回一个序列化后的 JSON 对象.</div>
+
+<div> </div>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">browser.runtime.getManifest()
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<p>无.</p>
+
+<h3 id="返回值">返回值</h3>
+
+<p>是一个能表示主文件所有信息的 JSON 对象.</p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.runtime.getManifest")}}</p>
+
+<h2 id="示例">示例</h2>
+
+<p>取得主文件中的 name 特性的值, 并输出到控制台:</p>
+
+<pre class="brush: js">var manifest = browser.runtime.getManifest();
+console.log(manifest.name);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime#method-getManifest"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/index.html
new file mode 100644
index 0000000000..5a1618e9e7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/index.html
@@ -0,0 +1,181 @@
+---
+title: runtime
+slug: Mozilla/Add-ons/WebExtensions/API/runtime
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - Interface
+ - NeedsTranslation
+ - Non-standard
+ - Reference
+ - TopicStub
+ - WebExtensions
+ - runtime
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime
+---
+<div>{{AddonSidebar}}</div>
+
+<p>该模块提供关于附加组件以及运行环境的信息。</p>
+
+<p>它提供一组消息通信API,允许你:</p>
+
+<ul>
+ <li>在附加组件的不同模块间通信。</li>
+ <li>和其它的附加组件通信。</li>
+ <li>和native应用通信。</li>
+</ul>
+
+<h2 id="Types">Types</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("runtime.Port")}}</dt>
+ <dd>表示两个特定上下文之间的连接的一端,可用于交换消息。</dd>
+ <dt>{{WebExtAPIRef("runtime.MessageSender")}}</dt>
+ <dd>
+ <div class="trans-right">
+ <div class="output-wrap small-font">
+ <div class="output-mod ordinary-wrap">
+ <div class="output-bd" dir="ltr" style="padding-bottom: 0px;">
+ <p class="ordinary-output target-output clearfix"><span>包含有关消息或连接请求的发件人的信息。</span></p>
+ </div>
+ </div>
+ </div>
+ </div>
+ </dd>
+ <dt>{{WebExtAPIRef("runtime.PlatformOs")}}</dt>
+ <dd>标识浏览器的操作系统。</dd>
+ <dt>{{WebExtAPIRef("runtime.PlatformArch")}}</dt>
+ <dd>标识浏览器的处理器架构。</dd>
+ <dt>{{WebExtAPIRef("runtime.PlatformInfo")}}</dt>
+ <dd>包含有关浏览器正在运行的平台的信息。</dd>
+ <dt>{{WebExtAPIRef("runtime.RequestUpdateCheckStatus")}}</dt>
+ <dd>{{WebExtAPIRef("runtime.requestUpdateCheck()")}} 的返回结果。</dd>
+ <dt>{{WebExtAPIRef("runtime.OnInstalledReason")}}</dt>
+ <dd>{{WebExtAPIRef("runtime.onInstalled")}} 事件被触发的原因。</dd>
+ <dt>{{WebExtAPIRef("runtime.OnRestartRequiredReason")}}</dt>
+ <dd>{{WebExtAPIRef("runtime.onRestartRequired")}} 事件被触发的原因。</dd>
+</dl>
+
+<h2 id="Properties">Properties</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("runtime.lastError")}}</dt>
+ <dd>当异步方法执行时发生了错误,它需要向其调用方报告时,该值会被设置。</dd>
+ <dt>{{WebExtAPIRef("runtime.id")}}</dt>
+ <dd>当前扩展的ID。</dd>
+</dl>
+
+<h2 id="Functions">Functions</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("runtime.getBackgroundPage()")}}</dt>
+ <dd>取得当前扩展的后台页的 <a href="https://wiki.developer.mozilla.org/zh-CN/docs/Web/API/Window">Window</a> 对象。</dd>
+ <dt>{{WebExtAPIRef("runtime.openOptionsPage()")}}</dt>
+ <dd>
+ <p>打开你的扩展的 <a href="/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Options_pages">选项页面</a>。</p>
+ </dd>
+ <dt>{{WebExtAPIRef("runtime.getManifest()")}}</dt>
+ <dd>获得完整的 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> 声明文件的序列化对象。</dd>
+ <dt>{{WebExtAPIRef("runtime.getURL()")}}</dt>
+ <dd>给定某个打包在扩展中的资源的基于 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> 相对路径,返回一个完整有效的 URL。</dd>
+ <dt>{{WebExtAPIRef("runtime.setUninstallURL()")}}</dt>
+ <dd>指定一个此扩展被卸载后打开的 URL。</dd>
+ <dt>{{WebExtAPIRef("runtime.reload()")}}</dt>
+ <dd>重新加载此扩展。</dd>
+ <dt>{{WebExtAPIRef("runtime.requestUpdateCheck()")}}</dt>
+ <dd>检查此扩展的更新。</dd>
+ <dt>{{WebExtAPIRef("runtime.connect()")}}</dt>
+ <dd>建立一个页面脚本到扩展主进程,或扩展主进程到页面脚本之间的通信连接。</dd>
+ <dt>{{WebExtAPIRef("runtime.connectNative()")}}</dt>
+ <dd>
+ <div>建立一个浏览器扩展与用户电脑上的原生应用的通信连接。</div>
+ </dd>
+ <dt>{{WebExtAPIRef("runtime.sendMessage()")}}</dt>
+ <dd>发送一条消息到此扩展或其他扩展的事件监听器,类似于  {{WebExtAPIRef('runtime.connect')}} 但只能发送一条消息,以及可选的响应处理函数。</dd>
+ <dt>{{WebExtAPIRef("runtime.sendNativeMessage()")}}</dt>
+ <dd>从扩展发送一条消息到原生应用。</dd>
+ <dt>{{WebExtAPIRef("runtime.getPlatformInfo()")}}</dt>
+ <dd>返回当前所在平台的信息。</dd>
+ <dt>{{WebExtAPIRef("runtime.getBrowserInfo()")}}</dt>
+ <dd>返回此扩展所在的浏览器的信息。</dd>
+ <dt>{{WebExtAPIRef("runtime.getPackageDirectoryEntry()")}}</dt>
+ <dd>返回此扩展所在目录的 DirectoryEntry。</dd>
+</dl>
+
+<h2 id="Events">Events</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("runtime.onStartup")}}</dt>
+ <dd>当一个拥有此扩展的账户第一次启动时触发,注意若处于隐私模式中则不会触发。</dd>
+ <dt>{{WebExtAPIRef("runtime.onInstalled")}}</dt>
+ <dd>当扩展第一次安装,扩展更新,浏览器更新后触发。</dd>
+ <dt>{{WebExtAPIRef("runtime.onSuspend")}}</dt>
+ <dd>当扩展将被停止前触发,使得扩展可以执行一些清理工作。</dd>
+ <dt>{{WebExtAPIRef("runtime.onSuspendCanceled")}}</dt>
+ <dd>在此事件 {{WebExtAPIRef("runtime.onSuspend")}} 后触发,表明扩展最终没有被停止。</dd>
+ <dt>{{WebExtAPIRef("runtime.onUpdateAvailable")}}</dt>
+ <dd>当扩展更新可用时触发,注意若扩展运行中,更新不会马上被安装。</dd>
+ <dt>{{WebExtAPIRef("runtime.onBrowserUpdateAvailable")}}</dt>
+ <dd>当浏览器更新可用时触发,注意浏览器需要重启才能安装更新。</dd>
+ <dt>{{WebExtAPIRef("runtime.onConnect")}}</dt>
+ <dd>与扩展进程或页面脚本(content script)建立通信连接时触发。</dd>
+ <dt>{{WebExtAPIRef("runtime.onConnectExternal")}}</dt>
+ <dd>与其他扩展建立通信连接时触发。</dd>
+ <dt>{{WebExtAPIRef("runtime.onMessage")}}</dt>
+ <dd>当收到扩展进程或页面脚本(content script)的消息时触发。</dd>
+ <dt>{{WebExtAPIRef("runtime.onMessageExternal")}}</dt>
+ <dd>当收到其他扩展的消息时触发,不能在页面脚本(content script)中使用。</dd>
+ <dt>{{WebExtAPIRef("runtime.onRestartRequired")}}</dt>
+ <dd>当设备要重启时触发。</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.runtime")}}</p>
+
+<div class="hidden note">
+<p>The "Chrome incompatibilities" section is included from <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> using the <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p>
+
+<p>If you need to update this content, edit <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, then shift-refresh this page to see your changes.</p>
+</div>
+
+<p>{{Compat("webextensions.api.runtime")}} {{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate">// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onconnect/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onconnect/index.html
new file mode 100644
index 0000000000..d51cb8abbc
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onconnect/index.html
@@ -0,0 +1,228 @@
+---
+title: runtime.onConnect
+slug: Mozilla/Add-ons/WebExtensions/API/runtime/onConnect
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/onConnect
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>当使用扩展处理或content script建立连接时触发.</p>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js">browser.runtime.onConnect.addListener(listener)
+browser.runtime.onConnect.removeListener(listener)
+browser.runtime.onConnect.hasListener(listener)
+</pre>
+
+<p>事件有三个方法:</p>
+
+<dl>
+ <dt><code>addListener(callback)</code></dt>
+ <dd>为 这个事件添加一个监听器.</dd>
+ <dt><code>removeListener(listener)</code></dt>
+ <dd>停止监听这个事件. <code>listener</code> 参数就是要移除的监听器.</dd>
+ <dt><code>hasListener(listener)</code></dt>
+ <dd>检查监听器是否已经注册到这个事件上. 如果已经监听,则返回 <code>true</code> 否则返回 <code>false</code>.</dd>
+</dl>
+
+<h2 id="addListener_语法">addListener 语法</h2>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>function</code></dt>
+ <dd>
+ <p>A callback function that will be called when this event occurs. The function will be passed the following arguments:</p>
+
+ <dl class="reference-values">
+ <dt><code>port</code></dt>
+ <dd>A {{WebExtAPIRef('runtime.Port')}} object connecting the current script to the other context it is connecting to.</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.runtime.onConnect")}}</p>
+
+<h2 id="Examples">Examples</h2>
+
+<p>This content script:</p>
+
+<ul>
+ <li>connects to the background script, and stores the <code>Port</code> in a variable <code>myPort</code></li>
+ <li>listens for messages on <code>myPort</code>, and logs them</li>
+ <li>sends messages to the background script, using <code>myPort</code>, when the user clicks the document</li>
+</ul>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="comment token">// content-script.js</span>
+
+<span class="keyword token">var</span> myPort <span class="operator token">=</span> browser<span class="punctuation token">.</span>runtime<span class="punctuation token">.</span><span class="function token">connect</span><span class="punctuation token">(</span><span class="punctuation token">{</span>name<span class="punctuation token">:</span><span class="string token">"port-from-cs"</span><span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+myPort<span class="punctuation token">.</span><span class="function token">postMessage</span><span class="punctuation token">(</span><span class="punctuation token">{</span>greeting<span class="punctuation token">:</span> <span class="string token">"hello from content script"</span><span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+myPort<span class="punctuation token">.</span>onMessage<span class="punctuation token">.</span><span class="function token">addListener</span><span class="punctuation token">(</span><span class="keyword token">function</span><span class="punctuation token">(</span>m<span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">"In content script, received message from background script: "</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>m<span class="punctuation token">.</span>greeting<span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+document<span class="punctuation token">.</span>body<span class="punctuation token">.</span><span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">"click"</span><span class="punctuation token">,</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ myPort<span class="punctuation token">.</span><span class="function token">postMessage</span><span class="punctuation token">(</span><span class="punctuation token">{</span>greeting<span class="punctuation token">:</span> <span class="string token">"they clicked the page!"</span><span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>The corresponding background script:</p>
+
+<ul>
+ <li>listens for connection attempts from the content script</li>
+ <li>when it receives a connection attempt:
+ <ul>
+ <li>stores the port in a variable named <code>portFromCS</code></li>
+ <li>sends the content script a message using the port</li>
+ <li>starts listening to messages received on the port, and logs them</li>
+ </ul>
+ </li>
+ <li>sends messages to the content script, using <code>portFromCS</code>, when the user clicks the extension's browser action</li>
+</ul>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="comment token">// background-script.js</span>
+
+<span class="keyword token">var</span> portFromCS<span class="punctuation token">;</span>
+
+<span class="keyword token">function</span> <span class="function token">connected</span><span class="punctuation token">(</span>p<span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ portFromCS <span class="operator token">=</span> p<span class="punctuation token">;</span>
+ portFromCS<span class="punctuation token">.</span><span class="function token">postMessage</span><span class="punctuation token">(</span><span class="punctuation token">{</span>greeting<span class="punctuation token">:</span> <span class="string token">"hi there content script!"</span><span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+ portFromCS<span class="punctuation token">.</span>onMessage<span class="punctuation token">.</span><span class="function token">addListener</span><span class="punctuation token">(</span><span class="keyword token">function</span><span class="punctuation token">(</span>m<span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">"In background script, received message from content script"</span><span class="punctuation token">)</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>m<span class="punctuation token">.</span>greeting<span class="punctuation token">)</span><span class="punctuation token">;</span>
+ <span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}</span>
+
+browser<span class="punctuation token">.</span>runtime<span class="punctuation token">.</span>onConnect<span class="punctuation token">.</span><span class="function token">addListener</span><span class="punctuation token">(</span>connected<span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+browser<span class="punctuation token">.</span>browserAction<span class="punctuation token">.</span>onClicked<span class="punctuation token">.</span><span class="function token">addListener</span><span class="punctuation token">(</span><span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ portFromCS<span class="punctuation token">.</span><span class="function token">postMessage</span><span class="punctuation token">(</span><span class="punctuation token">{</span>greeting<span class="punctuation token">:</span> <span class="string token">"they clicked the button!"</span><span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime#event-onConnect"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
+
+<div id="SL_balloon_obj" style="display: block;">
+<div class="SL_ImTranslatorLogo" id="SL_button" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%; opacity: 1; display: none; left: -8px; top: -25px;"> </div>
+
+<div id="SL_shadow_translation_result2" style="display: none;"> </div>
+
+<div id="SL_shadow_translator" style="display: none;">
+<div id="SL_planshet">
+<div id="SL_arrow_up" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;"> </div>
+
+<div id="SL_Bproviders">
+<div class="SL_BL_LABLE_ON" id="SL_P0" title="Google">G</div>
+
+<div class="SL_BL_LABLE_ON" id="SL_P1" title="Microsoft">M</div>
+
+<div class="SL_BL_LABLE_ON" id="SL_P2" title="Translator">T</div>
+</div>
+
+<div id="SL_alert_bbl" style="display: none;">
+<div id="SLHKclose" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;"> </div>
+
+<div id="SL_alert_cont"> </div>
+</div>
+
+<div id="SL_TB">
+<table id="SL_tables">
+ <tbody>
+ <tr>
+ <td class="SL_td"><input></td>
+ <td class="SL_td"><select><option value="auto">检测语言</option><option value="eo">世界语</option><option value="zh-CN">中文简体</option><option value="zh-TW">中文繁体</option><option value="da">丹麦语</option><option value="uk">乌克兰语</option><option value="uz">乌兹别克语</option><option value="ur">乌尔都语</option><option value="hy">亚美尼亚语</option><option value="ig">伊博语</option><option value="ru">俄语</option><option value="bg">保加利亚语</option><option value="si">僧伽罗语</option><option value="hr">克罗地亚语</option><option value="is">冰岛语</option><option value="gl">加利西亚语</option><option value="ca">加泰罗尼亚语</option><option value="hu">匈牙利语</option><option value="zu">南非祖鲁语</option><option value="kn">卡纳达语</option><option value="hi">印地语</option><option value="su">印尼巽他语</option><option value="jw">印尼爪哇语</option><option value="id">印尼语</option><option value="gu">古吉拉特语</option><option value="kk">哈萨克语</option><option value="tr">土耳其语</option><option value="tg">塔吉克语</option><option value="sr">塞尔维亚语</option><option value="st">塞索托语</option><option value="cy">威尔士语</option><option value="bn">孟加拉语</option><option value="ceb">宿务语</option><option value="ne">尼泊尔语</option><option value="eu">巴斯克语</option><option value="af">布尔语(南非荷兰语)</option><option value="iw">希伯来语</option><option value="el">希腊语</option><option value="de">德语</option><option value="it">意大利语</option><option value="yi">意第绪语</option><option value="la">拉丁语</option><option value="lv">拉脱维亚语</option><option value="no">挪威语</option><option value="cs">捷克语</option><option value="sk">斯洛伐克语</option><option value="sl">斯洛文尼亚语</option><option value="sw">斯瓦希里语</option><option value="pa">旁遮普语</option><option value="ja">日语</option><option value="ka">格鲁吉亚语</option><option value="mi">毛利语</option><option value="fr">法语</option><option value="pl">波兰语</option><option value="bs">波斯尼亚语</option><option value="fa">波斯语</option><option value="te">泰卢固语</option><option value="ta">泰米尔语</option><option value="th">泰语</option><option value="ht">海地克里奥尔语</option><option value="ga">爱尔兰语</option><option value="et">爱沙尼亚语</option><option value="sv">瑞典语</option><option value="be">白俄罗斯语</option><option value="lt">立陶宛语</option><option value="so">索马里语</option><option value="yo">约鲁巴语</option><option value="my">缅甸语</option><option value="ro">罗马尼亚语</option><option value="lo">老挝语</option><option value="fi">芬兰语</option><option value="hmn">苗语</option><option value="en">英语</option><option value="nl">荷兰语</option><option value="tl">菲律宾语</option><option value="pt">葡萄牙语</option><option value="mn">蒙古语</option><option value="es">西班牙语</option><option value="ha">豪萨语</option><option value="vi">越南语</option><option value="az">阿塞拜疆语</option><option value="sq">阿尔巴尼亚语</option><option value="ar">阿拉伯语</option><option value="ko">韩语</option><option value="mk">马其顿语</option><option value="mg">马尔加什语</option><option value="mr">马拉地语</option><option value="ml">马拉雅拉姆语</option><option value="ms">马来语</option><option value="mt">马耳他语</option><option value="km">高棉语</option><option value="ny">齐切瓦语</option></select></td>
+ <td class="SL_td">
+ <div id="SL_switch_b" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="切换语言"> </div>
+ </td>
+ <td class="SL_td"><select><option value="eo">世界语</option><option value="zh-CN">中文简体</option><option value="zh-TW">中文繁体</option><option value="da">丹麦语</option><option value="uk">乌克兰语</option><option value="uz">乌兹别克语</option><option value="ur">乌尔都语</option><option value="hy">亚美尼亚语</option><option value="ig">伊博语</option><option value="ru">俄语</option><option value="bg">保加利亚语</option><option value="si">僧伽罗语</option><option value="hr">克罗地亚语</option><option value="is">冰岛语</option><option value="gl">加利西亚语</option><option value="ca">加泰罗尼亚语</option><option value="hu">匈牙利语</option><option value="zu">南非祖鲁语</option><option value="kn">卡纳达语</option><option value="hi">印地语</option><option value="su">印尼巽他语</option><option value="jw">印尼爪哇语</option><option value="id">印尼语</option><option value="gu">古吉拉特语</option><option value="kk">哈萨克语</option><option value="tr">土耳其语</option><option value="tg">塔吉克语</option><option value="sr">塞尔维亚语</option><option value="st">塞索托语</option><option value="cy">威尔士语</option><option value="bn">孟加拉语</option><option value="ceb">宿务语</option><option value="ne">尼泊尔语</option><option value="eu">巴斯克语</option><option value="af">布尔语(南非荷兰语)</option><option value="iw">希伯来语</option><option value="el">希腊语</option><option value="de">德语</option><option value="it">意大利语</option><option value="yi">意第绪语</option><option value="la">拉丁语</option><option value="lv">拉脱维亚语</option><option value="no">挪威语</option><option value="cs">捷克语</option><option value="sk">斯洛伐克语</option><option value="sl">斯洛文尼亚语</option><option value="sw">斯瓦希里语</option><option value="pa">旁遮普语</option><option value="ja">日语</option><option value="ka">格鲁吉亚语</option><option value="mi">毛利语</option><option value="fr">法语</option><option value="pl">波兰语</option><option value="bs">波斯尼亚语</option><option value="fa">波斯语</option><option value="te">泰卢固语</option><option value="ta">泰米尔语</option><option value="th">泰语</option><option value="ht">海地克里奥尔语</option><option value="ga">爱尔兰语</option><option value="et">爱沙尼亚语</option><option value="sv">瑞典语</option><option value="be">白俄罗斯语</option><option value="lt">立陶宛语</option><option value="so">索马里语</option><option value="yo">约鲁巴语</option><option value="my">缅甸语</option><option value="ro">罗马尼亚语</option><option value="lo">老挝语</option><option value="fi">芬兰语</option><option value="hmn">苗语</option><option selected value="en">英语</option><option value="nl">荷兰语</option><option value="tl">菲律宾语</option><option value="pt">葡萄牙语</option><option value="mn">蒙古语</option><option value="es">西班牙语</option><option value="ha">豪萨语</option><option value="vi">越南语</option><option value="az">阿塞拜疆语</option><option value="sq">阿尔巴尼亚语</option><option value="ar">阿拉伯语</option><option value="ko">韩语</option><option value="mk">马其顿语</option><option value="mg">马尔加什语</option><option value="mr">马拉地语</option><option value="ml">马拉雅拉姆语</option><option value="ms">马来语</option><option value="mt">马耳他语</option><option value="km">高棉语</option><option value="ny">齐切瓦语</option></select></td>
+ <td class="SL_td">
+ <div id="SL_TTS_voice" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="聆听翻译"> </div>
+ </td>
+ <td class="SL_td">
+ <div class="SL_copy" id="SL_copy" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="复制译文"> </div>
+ </td>
+ <td class="SL_td">
+ <div id="SL_bbl_font_patch"> </div>
+
+ <div class="SL_bbl_font" id="SL_bbl_font" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="字体大小"> </div>
+ </td>
+ <td class="SL_td">
+ <div id="SL_bbl_help" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="帮助"> </div>
+ </td>
+ <td class="SL_td">
+ <div class="SL_pin_off" id="SL_pin" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="固定弹出窗口"> </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+</div>
+
+<div id="SL_shadow_translation_result" style=""> </div>
+
+<div class="SL_loading" id="SL_loading" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;"> </div>
+
+<div id="SL_player2"> </div>
+
+<div id="SL_alert100">文本转语音功能仅限200个字符</div>
+
+<div id="SL_Balloon_options" style="background: rgb(255, 255, 255) repeat scroll 0% 0%;">
+<div id="SL_arrow_down" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;"> </div>
+
+<table id="SL_tbl_opt" style="width: 100%;">
+ <tbody>
+ <tr>
+ <td><input></td>
+ <td>
+ <div id="SL_BBL_IMG" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="显示翻译器的按钮 3 秒"> </div>
+ </td>
+ <td><a class="SL_options" title="显示选项">选项</a> : <a class="SL_options" title="翻译历史记录">历史</a> : <a class="SL_options" title="反馈">反馈</a> : <a class="SL_options" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=GD9D8CPW8HFA2" title="作出一点点贡献">Donate</a></td>
+ <td><span id="SL_Balloon_Close" title="关闭">关闭</span></td>
+ </tr>
+ </tbody>
+</table>
+</div>
+</div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onmessage/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onmessage/index.html
new file mode 100644
index 0000000000..afa54c1aaf
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/onmessage/index.html
@@ -0,0 +1,307 @@
+---
+title: runtime.onMessage
+slug: Mozilla/Add-ons/WebExtensions/API/runtime/onMessage
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/onMessage
+---
+<div>{{AddonSidebar()}}</div>
+
+<div>利用此事件来监听来自你的扩展其他部分的消息。例如,使用:</div>
+
+<div></div>
+
+<ul>
+ <li>in a <a href="/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Content_scripts">content script</a>, to listen for messages from a <a href="/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts">background script.</a></li>
+ <li>in a background script, to listen for messages from a content script.</li>
+ <li>in an <a href="/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Options_pages">options page</a> or <a href="/en-US/Add-ons/WebExtensions/User_interface_components#Popups">popup</a> script, to listen for messages from a background script.</li>
+ <li>in a background script, to listen for messages from an options page or popup script.</li>
+</ul>
+
+<p>To send a message that is received by the <code>onMessage</code> listener, use {{WebExtAPIRef("runtime.sendMessage()")}} or (to send a message to a content script) {{WebExtAPIRef("tabs.sendMessage()")}}.</p>
+
+<div class="blockIndicator note">
+<p>Avoid creating multiple <code>onMessage</code> listeners for the same type of message, as the order in which multiple listeners will fire is not guaranteed. Where you want to guarantee the delivery of a message to a specific end point, use the <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#Connection-based_messaging">connection-based approach to exchange messages</a>.</p>
+</div>
+
+<p>Along with the message itself, the listener is passed:</p>
+
+<ul>
+ <li>a <code>sender</code> object giving details about the message sender.</li>
+ <li>a <code>sendResponse</code> function that can be used to send a response back to the sender.</li>
+</ul>
+
+<p>You can send a synchronous response to the message by calling the <code>sendResponse</code> function inside your listener. <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/onMessage#Sending_a_synchronous_response">See an example</a>.</p>
+
+<p>To send an asynchronous response, there are two options:</p>
+
+<ul>
+ <li>return <code>true</code> from the event listener. This keeps the <code>sendResponse</code> function valid after the listener returns, so you can call it later. <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/onMessage#Sending_an_asynchronous_response_using_sendResponse">See an example</a>.</li>
+ <li>return a <code>Promise</code> from the event listener, and resolve when you have the response (or reject it in case of an error). <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/onMessage#Sending_an_asynchronous_response_using_a_Promise">See an example</a>.</li>
+</ul>
+
+<div class="warning">
+<p>Returning a <code>Promise</code> is now preferred as <code>sendResponse</code> <a href="https://github.com/mozilla/webextension-polyfill/issues/16#issuecomment-296693219">will be removed from the W3C spec</a>. The popular <a href="https://github.com/mozilla/webextension-polyfill">webextension-polyfill</a> library has already removed the <code>sendResponse</code> function from its implementation.</p>
+</div>
+
+<div class="blockIndicator note">
+<p>You can also use a <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#Connection-based_messaging">connection-based approach to exchange messages</a>.</p>
+</div>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js">browser.runtime.onMessage.addListener(listener)
+browser.runtime.onMessage.removeListener(listener)
+browser.runtime.onMessage.hasListener(listener)
+</pre>
+
+<p>Events have three functions:</p>
+
+<dl>
+ <dt><code>addListener(callback)</code></dt>
+ <dd>Adds a listener to this event.</dd>
+ <dt><code>removeListener(listener)</code></dt>
+ <dd>Stop listening to this event. The <code>listener</code> argument is the listener to remove.</dd>
+ <dt><code>hasListener(listener)</code></dt>
+ <dd>Checks whether a <code>listener</code> is registered for this event. Returns <code>true</code> if it is listening, <code>false</code> otherwise.</dd>
+</dl>
+
+<h2 id="addListener_syntax">addListener syntax</h2>
+
+<h3 id="Parameters">Parameters</h3>
+
+<dl>
+ <dt><code>function</code></dt>
+ <dd>
+ <p>A listener function that will be called when this event occurs. The function will be passed the following arguments:</p>
+
+ <dl class="reference-values">
+ <dt><code>message</code></dt>
+ <dd><code>object</code>. The message itself. This is a JSON-ifiable object.</dd>
+ </dl>
+
+ <dl class="reference-values">
+ <dt><code>sender</code></dt>
+ <dd>A {{WebExtAPIRef('runtime.MessageSender')}} object representing the sender of the message.</dd>
+ </dl>
+
+ <dl class="reference-values">
+ <dt><code>sendResponse</code></dt>
+ <dd>
+ <p>A function to call, at most once, to send a response to the message. The function takes a single argument, which may be any JSON-ifiable object. This argument is passed back to the message sender.</p>
+
+ <p>If you have more than one <code>onMessage</code> listener in the same document, then only one may send a response.</p>
+
+ <p>To send a response synchronously, call <code>sendResponse</code> before the listener function returns. To send a response asynchronously:</p>
+
+ <ul>
+ <li>either keep a reference to the <code>sendResponse</code> argument and return <code>true</code> from the listener function. You will then be able to call <code>sendResponse</code> after the listener function has returned.</li>
+ <li>or return a <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> from the listener function and resolve the promise when the response is ready. This is a preferred way.</li>
+ </ul>
+ </dd>
+ </dl>
+
+ <p>The listener function can return either a Boolean or a <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>.</p>
+
+ <div class="blockIndicator warning">
+ <p>Do not call <code>addListener</code> using the <code>async</code> function, as in:</p>
+
+ <pre><code>browser.runtime.onMessage.addListener(async (data, sender) =&gt; {
+ if (data.type === 'handle_me') return 'done';
+});
+</code></pre>
+
+ <p>as the listener will consume every message it receives, effectively blocking all other listeners from receiving and processing messages.</p>
+
+ <p>If you want to take an asynchronous approach, use a promise instead, as in:</p>
+
+ <pre><code>browser.runtime.onMessage.addListener(data, sender) =&gt; {
+ if (data.type === 'handle_me') return Promise.resolve('done');
+});
+</code></pre>
+ </div>
+ </dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.runtime.onMessage")}}</p>
+
+<h2 id="Examples">Examples</h2>
+
+<h3 id="Simple_example">Simple example</h3>
+
+<p>This content script listens for click events on the web page. If the click was on a link, it messages the background page with the target URL:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="comment token">// content-script.js</span>
+
+window<span class="punctuation token">.</span><span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">"click"</span><span class="punctuation token">,</span> notifyExtension<span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+<span class="keyword token">function</span> <span class="function token">notifyExtension</span><span class="punctuation token">(</span>e<span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ <span class="keyword token">if</span> <span class="punctuation token">(</span>e<span class="punctuation token">.</span>target<span class="punctuation token">.</span>tagName <span class="operator token">!=</span> <span class="string token">"A"</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ <span class="keyword token">return</span><span class="punctuation token">;</span>
+ <span class="punctuation token">}</span>
+ browser<span class="punctuation token">.</span>runtime<span class="punctuation token">.</span><span class="function token">sendMessage</span><span class="punctuation token">(</span><span class="punctuation token">{</span><span class="string token">"url"</span><span class="punctuation token">:</span> e<span class="punctuation token">.</span>target<span class="punctuation token">.</span>href<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;
+}</span></code>
+</pre>
+
+<p>The background script listens for these messages and displays a notification using the <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/notifications">notifications</a></code> API:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="comment token">// background-script.js</span>
+
+browser<span class="punctuation token">.</span>runtime<span class="punctuation token">.</span>onMessage<span class="punctuation token">.</span><span class="function token">addListener</span><span class="punctuation token">(</span>notify<span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+<span class="keyword token">function</span> <span class="function token">notify</span><span class="punctuation token">(</span>message<span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ browser<span class="punctuation token">.</span>notifications<span class="punctuation token">.</span><span class="function token">create</span><span class="punctuation token">(</span><span class="punctuation token">{</span>
+ <span class="string token">"type"</span><span class="punctuation token">:</span> <span class="string token">"basic"</span><span class="punctuation token">,</span>
+ <span class="string token">"iconUrl"</span><span class="punctuation token">:</span> browser<span class="punctuation token">.</span>extension<span class="punctuation token">.</span><span class="function token">getURL</span><span class="punctuation token">(</span><span class="string token">"link.png"</span><span class="punctuation token">)</span><span class="punctuation token">,</span>
+ <span class="string token">"title"</span><span class="punctuation token">:</span> <span class="string token">"You clicked a link!"</span><span class="punctuation token">,</span>
+ <span class="string token">"message"</span><span class="punctuation token">:</span> message<span class="punctuation token">.</span>url
+ <span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}</span></code></pre>
+
+<h3 id="Sending_a_synchronous_response">Sending a synchronous response</h3>
+
+<p>This content script sends a message to the background script when the user clicks on the page. It also logs any response sent by the background script:</p>
+
+<pre class="brush: js">// content-script.js
+
+function handleResponse(message) {
+ console.log(`background script sent a response: ${message.response}`);
+}
+
+function handleError(error) {
+ console.log(`Error: ${error}`);
+}
+
+function sendMessage(e) {
+ var sending = browser.runtime.sendMessage({content: "message from the content script"});
+ sending.then(handleResponse, handleError);
+}
+
+window.addEventListener("click", sendMessage);</pre>
+
+<p>Here is a version of the corresponding background script, that sends a response synchronously, from inside in the listener:</p>
+
+<pre class="brush: js">// background-script.js
+
+function handleMessage(request, sender, sendResponse) {
+ console.log(`content script sent a message: ${request.content}`);
+ sendResponse({response: "response from background script"});
+}
+
+browser.runtime.onMessage.addListener(handleMessage);</pre>
+
+<p>And here is another version, that uses Promise.resolve():</p>
+
+<pre class="brush: js">// background-script.js
+
+function handleMessage(request, sender, sendResponse) {
+ console.log(`content script sent a message: ${request.content}`);
+ return Promise.resolve({response: "response from background script"});
+}
+
+browser.runtime.onMessage.addListener(handleMessage);</pre>
+
+<h3 id="Sending_an_asynchronous_response_using_sendResponse">Sending an asynchronous response using sendResponse</h3>
+
+<p>Here is an alternative version of the background script from the previous example. It sends a response asynchronously after the listener has returned. Note <code>return true;</code> in the listener: this tells the browser that you intend to use the <code>sendResponse</code> argument after the listener has returned.</p>
+
+<pre class="brush: js">// background-script.js
+
+function handleMessage(request, sender, sendResponse) {
+ console.log(`content script sent a message: ${request.content}`);
+ setTimeout(() =&gt; {
+ sendResponse({response: "async response from background script"});
+ }, 1000);
+ return true;
+}
+
+browser.runtime.onMessage.addListener(handleMessage);
+</pre>
+
+<h3 id="Sending_an_asynchronous_response_using_a_Promise">Sending an asynchronous response using a Promise</h3>
+
+<p>This content script gets the first &lt;a&gt; link on the page and sends a message asking if the link's location is bookmarked. It expects to get a Boolean response: <code>true</code> if the location is bookmarked, <code>false</code> otherwise:</p>
+
+<pre class="brush: js">// content-script.js
+
+const firstLink = document.querySelector("a");
+
+function handleResponse(isBookmarked) {
+ if (isBookmarked) {
+ firstLink.classList.add("bookmarked");
+ }
+}
+
+browser.runtime.sendMessage({
+ url: firstLink.href
+}).then(handleResponse);</pre>
+
+<p>Here is the background script. It uses <code>{{WebExtAPIRef("bookmarks.search()")}}</code> to see if the link is bookmarked, which returns a <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>:</p>
+
+<pre class="brush: js">// background-script.js
+
+function isBookmarked(message, sender, response) {
+ return browser.bookmarks.search({
+ url: message.url
+ }).then(function(results) {
+ return results.length &gt; 0;
+ });
+}
+
+browser.runtime.onMessage.addListener(isBookmarked);</pre>
+
+<p>If the asynchronous handler doesn't return a promise, you can explicitly construct a promise. This rather contrived example sends a response after a 1-second delay, using <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">Window.setTimeout()</a></code>:</p>
+
+<pre class="brush: js">// background-script.js
+
+function handleMessage(request, sender, sendResponse) {
+ return new Promise(resolve =&gt; {
+ setTimeout(() =&gt; {
+ resolve({response: "async response from background script"});
+ }, 1000);
+ });
+}
+
+browser.runtime.onMessage.addListener(handleMessage);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime#event-onMessage"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/openoptionspage/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/openoptionspage/index.html
new file mode 100644
index 0000000000..701af9c2ea
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/openoptionspage/index.html
@@ -0,0 +1,92 @@
+---
+title: runtime.openOptionsPage()
+slug: Mozilla/Add-ons/WebExtensions/API/runtime/openOptionsPage
+tags:
+ - API
+ - OpenPractices
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/openOptionsPage
+---
+<div> </div>
+
+<div>假如你的页面有<a href="/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Options_pages">options page</a>(设置页面)的定义,使用此方法打开它。</div>
+
+<div> </div>
+
+<div>这是一个异步方法,返回一个 <code style="font-style: normal; font-weight: normal;"><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>对象</code></div>
+
+<div> </div>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">var openingPage = browser.runtime.openOptionsPage()
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<p>无</p>
+
+<h3 id="返回值">返回值</h3>
+
+<p><code>当设置页面成功创建,执行<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>的无参成功回调方法,否则执行<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a>的失败回调方法,参数为错误信息。</code></p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.runtime.openOptionsPage")}}</p>
+
+<h2 id="例子">例子</h2>
+
+<p>当用户点击浏览器行为图标时,打开一个设置页面。</p>
+
+<pre class="brush: js">function onOpened() {
+ console.log(`Options page opened`);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+var opening = browser.runtime.openOptionsPage();
+opening.then(onOpened, onError);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime#method-openOptionsPage"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformarch/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformarch/index.html
new file mode 100644
index 0000000000..0adfaf39f1
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformarch/index.html
@@ -0,0 +1,70 @@
+---
+title: 获取处理器架构 - runtime.PlatformArch
+slug: Mozilla/Add-ons/WebExtensions/API/runtime/PlatformArch
+tags:
+ - 获取处理器架构
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/PlatformArch
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>当前浏览器所在的计算机的处理器架构.</p>
+
+<h2 id="值类型">值类型</h2>
+
+<p>该值的类型是字符串. 可能的值如下:</p>
+
+<dl>
+ <dt><code>"arm"</code></dt>
+ <dd>标识平台基于 arm 架构.</dd>
+ <dt><code>"x86-32"</code></dt>
+ <dd>表示平台基于 x86 32-bit 架构.</dd>
+ <dt><code>"x86-64"</code></dt>
+ <dd>表示平台基于 x86 64-bit 架构.</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.runtime.PlatformArch")}}</p>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime#type-PlatformArch"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformos/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformos/index.html
new file mode 100644
index 0000000000..6c32d46b6f
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/platformos/index.html
@@ -0,0 +1,76 @@
+---
+title: 获取当前操作系统 - runtime.PlatformOs
+slug: Mozilla/Add-ons/WebExtensions/API/runtime/PlatformOs
+tags:
+ - 获取当前操作系统
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/PlatformOs
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>获取当前浏览器运行所在的操作系统.</p>
+
+<h2 id="值类型">值类型</h2>
+
+<p>该值的类型是字符串. 可能的值如下:</p>
+
+<dl>
+ <dt><code>"mac"</code></dt>
+ <dd>表示底层操作系统是 Mac OS X.</dd>
+ <dt><code>"win"</code></dt>
+ <dd>表示底层操作系统是 Windows.</dd>
+ <dt><code>"android"</code></dt>
+ <dd>表示底层操作系统是 Android.</dd>
+ <dt><code>"cros"</code></dt>
+ <dd>表示底层操作系统是 Chrome OS.</dd>
+ <dt><code>"linux"</code></dt>
+ <dd>表示底层操作系统是 Linux.</dd>
+ <dt><code>"openbsd"</code></dt>
+ <dd>表示底层操作系统是 Open/FreeBSD.</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.runtime.PlatformOs")}}</p>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime#type-PlatformOs"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendmessage/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendmessage/index.html
new file mode 100644
index 0000000000..86ec753075
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendmessage/index.html
@@ -0,0 +1,157 @@
+---
+title: runtime.sendMessage()
+slug: Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage
+---
+<div>{{AddonSidebar()}}</div>
+
+<div>向你的扩展或其他扩展发送单条消息。</div>
+
+<div> </div>
+
+<div>如果想发给你自己的扩展,则省略 <code>extensionId</code> 参数。扩展中所有页面的{{WebExtAPIRef('runtime.onMessage')}}将会被触发,除了调用<code>runtime.sendMessage的页面。</code></div>
+
+<p> </p>
+
+<p>如果发送给其他扩展,则将参数 <code>extensionId</code> 设置为其他扩展的ID。其他扩展的 {{WebExtAPIRef('runtime.onMessageExternal')}} 将会被触发。</p>
+
+<p>此接口不能给 content script 发消息,如果要给 content script 发消息,请使用 {{WebExtAPIRef('tabs.sendMessage')}}。</p>
+
+<p>这是个异步方法,将返回一个 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>。</p>
+
+<p>Syntax</p>
+
+<pre class="syntaxbox brush:js">var sending = browser.runtime.sendMessage(
+ extensionId, // optional string
+ message, // any
+ options // optional object
+)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>extensionId</code>{{optional_inline}}</dt>
+ <dd><code>string</code>. 若你想要发给不同的扩展,这里传入接收方的扩展ID。The ID of the extension to send the message to. Include this to send the message to a different extension. If the intended recipient has set an ID explicitly using the <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications">applications</a> key in manifest.json, then <code>extensionId</code> should have this value. Otherwise it should be have the ID that was generated for the intended recipient.</dd>
+ <dd>若此省略此参数,则发送给自己的扩展。</dd>
+ <dt><code>message</code></dt>
+ <dd><code>any</code>. 任何可以序列化成JSON的东西。</dd>
+ <dt><code>options</code>{{optional_inline}}</dt>
+ <dd><code>object</code>.
+ <dl class="reference-values">
+ <dt><code>includeTlsChannelId</code>{{optional_inline}}</dt>
+ <dd><code>boolean</code>. Whether the TLS channel ID will be passed into {{WebExtAPIRef('runtime.onMessageExternal')}} for processes that are listening for the connection event.</dd>
+ <dt><code>toProxyScript{{optional_inline}}</code></dt>
+ <dd><code>boolean</code>. Must be True if the message is intended for a PAC file loaded using the {{WebExtAPIRef("proxy")}} API.</dd>
+ </dl>
+ </dd>
+</dl>
+
+<p>根据给出的参数不同,API遵循如下规则:</p>
+
+<ul>
+ <li><strong>只有1个参数:</strong>将会被当做 message 发送给自己的扩展。</li>
+ <li><strong>有2个参数:</strong>
+ <ul>
+ <li>若第二个参数符合下面的规则,将会被当做 <code>(message, options)</code>,将消息发送给自己的扩展:
+ <ol>
+ <li>一个合法的配置对象(也就是说这个对象只包含options参数支持的属性)</li>
+ <li>null</li>
+ <li>undefined</li>
+ </ol>
+ </li>
+ <li>否则,将会被当做 <code>(extensionId, message)。</code>消息将会给发送给 <code>extensionId</code> 指定ID的扩展</li>
+ </ul>
+ </li>
+ <li><strong>有3个参数:</strong>将会被当做 <code>(extensionId, message, options)</code>. 消息将会给发送给 <code>extensionId</code> 指定ID的扩展</li>
+</ul>
+
+<div class="note">
+<p>在Firefox 55之前,只给出2个参数时,规则会有所不同:<br>
+ Under the old rules, if the first argument was a string, it was treated as the <code>extensionId</code>, with the message as the second argument. This meant that if you called <code>sendMessage()</code> with arguments like <code>("my-message", {})</code>, then it would send an empty message to the extension identified by "my-message". Under the new rules, with these arguments you would send the message "my-message" internally, with an empty options object.</p>
+</div>
+
+<h3 id="Return_value">Return value</h3>
+
+<p>返回一个 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>。若接收方响应,Promise将会变为 fulfilled 并且返回接收方响应的JSON对象(数字、字符串、数组、true/false都是合法的JSON对象)。否则,Promise会变为 fulfilled 但是不返回任何参数。如果发生了连接错误,Promise将会变为 rejected 并返回一个错误消息。</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.runtime.sendMessage")}}</p>
+
+<h2 id="Examples">Examples</h2>
+
+<p>Here's a content script that sends a message to the background script when the user clicks the content window. The message payload is <code>{greeting: "Greeting from the content script"}</code>, and the sender also expects to get a response, which is handled in the <code>handleResponse</code> function:</p>
+
+<pre class="brush: js">// content-script.js
+
+function handleResponse(message) {
+ console.log(`Message from the background script: ${message.response}`);
+}
+
+function handleError(error) {
+ console.log(`Error: ${error}`);
+}
+
+function notifyBackgroundPage(e) {
+ var sending = browser.runtime.sendMessage({
+ greeting: "Greeting from the content script"
+ });
+ sending.then(handleResponse, handleError);
+}
+
+window.addEventListener("click", notifyBackgroundPage);</pre>
+
+<p>The corresponding background script looks like this:</p>
+
+<pre class="brush: js">// background-script.js
+
+function handleMessage(request, sender, sendResponse) {
+ console.log("Message from the content script: " +
+ request.greeting);
+ sendResponse({response: "Response from background script"});
+}
+
+browser.runtime.onMessage.addListener(handleMessage);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/runtime#method-sendMessage"><code>chrome.runtime</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendnativemessage/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendnativemessage/index.html
new file mode 100644
index 0000000000..349b7a06d0
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/runtime/sendnativemessage/index.html
@@ -0,0 +1,109 @@
+---
+title: runtime.sendNativeMessage()
+slug: Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage
+tags:
+ - sendNativeMessage
+ - 扩展
+ - 附加组件
+ - 非标准
+translation_of: Mozilla/Add-ons/WebExtensions/API/runtime/sendNativeMessage
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>从 WebExtension 发送单条消息到 native application。</p>
+
+<p>它需要两个强制的参数:native application 的名字和要发送给它的JSON对象。浏览器将会加载 native application 然后发送这个消息。</p>
+
+<p>这是一个异步函数,返回一个 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>对象。native application 发送的第一条消息将被当作<code>sendNativeMessage()</code> 的回复,并且 promise 将这个消息作为参数.。注意你不能使用 {{WebExtAPIRef("runtime.onMessage")}} 从应用获取回复:你必须使用回调函数来替代。</p>
+
+<p>每次调用 <code>runtime.sendNativeMessage()</code>都会生成一个新的实例。浏览器将会在收到回复后结束这个 native application。为了结束这个 native application,浏览器将会关闭 pipe,并给进程几秒的时间优雅的退出,如果它没有关闭就杀死它。</p>
+
+<p>更对信息,参考 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_messaging">Native messaging</a>。</p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">var sending = browser.runtime.sendNativeMessage(
+ application, // string
+ message // object
+)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>application</code></dt>
+ <dd><code>字符串类型。</code>native application的名字。它必须和 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Native_messaging#App_manifest">native application's manifest file</a>中的‘name’字段一致。</dd>
+ <dt><code>message</code></dt>
+ <dd><code>对象类型。一个将要发送给</code> native application的JSON对象。</dd>
+</dl>
+
+<h3 id="返回值">返回值</h3>
+
+<p>一个 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>对象。如果native application发送了一个回复,它将会填充回复的JSON对象作为参数。否则它不会填充参数。如果在native application连接期间发生了错误,promise将会被一个错误的消息拒绝。</p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">这个页面的兼容性表从结构性数据生成的。如果你想提供数据,请访问 <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 然后提交请求。</p>
+
+<p>{{Compat("webextensions.api.runtime.sendNativeMessage")}}</p>
+
+<h2 id="示例">示例</h2>
+
+<p>这是一个 background script ,当使用者点击浏览器的browser action时,它会发送 "ping" 消息到 "ping_pong" 应用并且把回复记录下来:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">function</span> <span class="function token">onResponse</span><span class="punctuation token">(</span>response<span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">`Received ${</span>response}<span class="punctuation token">`)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}
+
+</span></code>function onError(error) {
+  console.log(`Error: ${error}`);
+}<code class="language-js">
+
+<span class="comment token">/*
+On a click on the browser action, send the app a message.
+*/</span>
+browser<span class="punctuation token">.</span>browserAction<span class="punctuation token">.</span>onClicked<span class="punctuation token">.</span><span class="function token">addListener</span><span class="punctuation token">(</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="operator token">=</span><span class="operator token">&gt;</span> <span class="punctuation token">{</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="string token">"Sending: ping"</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+ var sending = browser<span class="punctuation token">.</span>runtime<span class="punctuation token">.</span><span class="function token">sendNativeMessage</span><span class="punctuation token">(</span><span class="string token">"ping_pong"</span><span class="punctuation token">,</span> <span class="string token">"ping"</span><span class="punctuation token">)</span><span class="punctuation token">;
+ sending.then(onResponse, onError);</span>
+<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>这个API 基于 Chromium 的 <a href="https://developer.chrome.com/extensions/runtime#method-sendNativeMessage"><code>chrome.runtime</code></a> API。 本文来自 Chromium 代码中的 <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/runtime.json"><code>runtime.json</code></a> 。</p>
+
+<p>微软 Edge 的兼容性数据由 Microsoft Corporation 提供,并且包含在这里基于 Creative Commons Attribution 3.0 United States License。</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/search/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/search/index.html
new file mode 100644
index 0000000000..4a8c5e320b
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/search/index.html
@@ -0,0 +1,34 @@
+---
+title: search
+slug: Mozilla/Add-ons/WebExtensions/API/search
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - NeedsTranslation
+ - Reference
+ - Search
+ - Search Engines
+ - TopicStub
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/API/search
+---
+<div>{{AddonSidebar}}</div>
+
+<p>Retrieves search engines and executes a search with a specific search engine.</p>
+
+<p>To use this API you need to have the <code>"search"</code> <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>.</p>
+
+<h2 id="Functions">Functions</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("search.get()")}}</dt>
+ <dd>Retrieve all search engines.</dd>
+ <dt>{{WebExtAPIRef("search.search()")}}</dt>
+ <dd>Search using the specified search engine.</dd>
+ <dt>
+ <h2 id="Browser_compatibility">Browser compatibility</h2>
+ </dt>
+</dl>
+
+<p>{{Compat("webextensions.api.search", 1, 1)}} {{WebExtExamples("h2")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/search/search/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/search/search/index.html
new file mode 100644
index 0000000000..bb3a122a64
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/search/search/index.html
@@ -0,0 +1,93 @@
+---
+title: search.search()
+slug: Mozilla/Add-ons/WebExtensions/API/search/search
+translation_of: Mozilla/Add-ons/WebExtensions/API/search/search
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>使用指定的搜索引擎或默认搜索引擎进行搜索。</p>
+
+<p>结果将显示在一个新的选项卡中,或者如果给出了tabId参数,则显示在由此标识的选项卡中。</p>
+
+<p>要在扩展程序中使用此功能,您必须要求<code>"search"</code> <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">有明确许可</a>.</p>
+
+<p>获取安装的搜索引擎, 请使用 {{WebExtAPIRef("search.get()")}}.</p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js notranslate">browser.search.search(
+ searchProperties // object
+)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl class="reference-values">
+ <dt><code>searchProperties</code></dt>
+ <dd>
+ <p><code>object</code>. 拥有以下属性的对象:</p>
+
+ <dl class="reference-values">
+ <dt><code>query</code></dt>
+ <dd><code>字符串</code>. 进行查询的内容。</dd>
+ <dt><code>engine</code>{{optional_inline}}</dt>
+ <dd>
+ <p><code>字符串。</code>.搜索引擎的名称。 如果指定的搜索引擎名称不存在,该函数将引发错误。 如果省略此属性,则使用默认的搜索引擎。</p>
+ </dd>
+ <dt><code>tabId</code>{{optional_inline}}</dt>
+ <dd>
+ <p><font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">整型。</span></font>用于显示搜索结果的选项卡。如果省略此属性,搜索结果将显示在新选项卡中。</p>
+ </dd>
+ </dl>
+ </dd>
+</dl>
+
+<h3 id="返回值">返回值</h3>
+
+<p>无.</p>
+
+<h2 id="浏览器兼容">浏览器兼容</h2>
+
+<p class="hidden">此页面中的兼容性表是根据结构化数据生成的。 如果您想贡献数据,请查看<a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> ,并向我们发送请求请求。</p>
+
+<p>{{Compat("webextensions.api.search.search", 10)}}</p>
+
+<h2 id="例子">例子</h2>
+
+<p>使用默认搜索引擎进行搜索。 结果显示在新选项卡中:</p>
+
+<pre class="brush: js no-line-numbers notranslate">function search() {
+ browser.search.search({
+ query: "styracosaurus"
+ });
+}
+
+browser.browserAction.onClicked.addListener(search);
+</pre>
+
+<p>使用维基百科进行搜索。 结果显示在新选项卡中:</p>
+
+<pre class="brush: js no-line-numbers notranslate">function search() {
+ browser.search.search({
+ query: "styracosaurus",
+ engine: "Wikipedia (en)"
+ });
+}
+
+browser.browserAction.onClicked.addListener(search);
+</pre>
+
+<p>使用维基百科进行搜索。 结果将显示在活动选项卡中:</p>
+
+<pre class="brush: js no-line-numbers notranslate">function search(tab) {
+ browser.search.search({
+ query: "styracosaurus",
+ engine: "Wikipedia (en)",
+ tabId: tab.id
+ });
+}
+
+browser.browserAction.onClicked.addListener(search);
+</pre>
+
+<p>{{WebExtExamples}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/sessions/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/sessions/index.html
new file mode 100644
index 0000000000..65afc6692b
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/sessions/index.html
@@ -0,0 +1,136 @@
+---
+title: sessions
+slug: Mozilla/Add-ons/WebExtensions/API/sessions
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - NeedsTranslation
+ - Non-standard
+ - Reference
+ - TopicStub
+ - WebExtensions
+ - sessions
+translation_of: Mozilla/Add-ons/WebExtensions/API/sessions
+---
+<div>{{AddonSidebar}}</div>
+
+<p>Use the sessions API to list, and restore, tabs and windows that have been closed while the browser has been running.</p>
+
+<p>The {{WebExtAPIRef("sessions.getRecentlyClosed()")}} function returns an array of {{WebExtAPIRef("tabs.Tab")}} and {{WebExtAPIRef("windows.Window")}} objects, representing tabs and windows that have been closed since the browser was running, up to the maximum defined in {{WebExtAPIRef("sessions.MAX_SESSION_RESULTS")}}.</p>
+
+<p>You can then restore a window or tab using the {{WebExtAPIRef("sessions.restore()")}} function. Restoring doesn't just reopen the tab: it also restores the tab's navigation history so the back/forward buttons will work.</p>
+
+<p>This API also provides a group of functions that enable an extension to store additional state associated with a tab or a window. Then, if the tab or window is closed and subsequently restored, the extension can retrieve the state. For example, a tab grouping extension might use this to remember which group a tab is in, so as to restore it into the right group if the user restores the tab.</p>
+
+<p>To use the sessions API you must have the "sessions" <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">API permission</a>.</p>
+
+<h2 id="Types">Types</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("sessions.Filter")}}</dt>
+ <dd>Enables you to restrict the number of {{WebExtAPIRef("sessions.Session", "Session")}} objects returned by a call to {{WebExtAPIRef("sessions.getRecentlyClosed()")}}.</dd>
+ <dt>{{WebExtAPIRef("sessions.Session")}}</dt>
+ <dd>
+ <p>Represents a tab or window that the user has closed in the current browsing session.</p>
+ </dd>
+</dl>
+
+<h2 id="Properties">Properties</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("sessions.MAX_SESSION_RESULTS")}}</dt>
+ <dd>The maximum number of sessions that will be returned by a call to <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/sessions/getRecentlyClosed" title="Returns an array Session objects, representing windows and tabs that were closed in the current browsing session (that is: the time since the browser was started)."><code>sessions.getRecentlyClosed()</code></a>.</dd>
+</dl>
+
+<h2 id="Functions">Functions</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("sessions.forgetClosedTab()")}}</dt>
+ <dd>Removes a closed tab from the browser's list of recently closed tabs.</dd>
+ <dt>{{WebExtAPIRef("sessions.forgetClosedWindow()")}}</dt>
+ <dd>Removes a closed window from the browser's list of recently closed windows.</dd>
+ <dt>{{WebExtAPIRef("sessions.getRecentlyClosed()")}}</dt>
+ <dd>Returns an array of {{WebExtAPIRef("sessions.Session", "Session")}} objects, representing windows and tabs that were closed in the current browsing session (that is: the time since the browser was started).</dd>
+ <dt>{{WebExtAPIRef("sessions.restore()")}}</dt>
+ <dd>
+ <p>Restores a closed tab or window.</p>
+ </dd>
+ <dt>{{WebExtAPIRef("sessions.setTabValue()")}}</dt>
+ <dd>
+ <p>Store a key/value pair associated with a given tab.</p>
+ </dd>
+ <dt>{{WebExtAPIRef("sessions.getTabValue()")}}</dt>
+ <dd>
+ <p>Retrieve a previously stored value for a given tab, given its key.</p>
+ </dd>
+ <dt>{{WebExtAPIRef("sessions.removeTabValue()")}}</dt>
+ <dd>
+ <p>Remove a key/value pair from a given tab.</p>
+ </dd>
+ <dt>{{WebExtAPIRef("sessions.setWindowValue()")}}</dt>
+ <dd>
+ <p>Store a key/value pair associated with a given window.</p>
+ </dd>
+ <dt>{{WebExtAPIRef("sessions.getWindowValue()")}}</dt>
+ <dd>
+ <p>Retrieve a previously stored value for a given window, given its key.</p>
+ </dd>
+ <dt>{{WebExtAPIRef("sessions.removeWindowValue()")}}</dt>
+ <dd>
+ <p>Remove a key/value pair from a given window.</p>
+ </dd>
+</dl>
+
+<h2 id="Events">Events</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("sessions.onChanged")}}</dt>
+ <dd>
+ <p>Fired when a tab or window is closed.</p>
+ </dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.sessions")}}</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/sessions"><code>chrome.sessions</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate">// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/sessions/session/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/sessions/session/index.html
new file mode 100644
index 0000000000..8b0c86204d
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/sessions/session/index.html
@@ -0,0 +1,78 @@
+---
+title: sessions.Session
+slug: Mozilla/Add-ons/WebExtensions/API/sessions/Session
+translation_of: Mozilla/Add-ons/WebExtensions/API/sessions/Session
+---
+<div><font><font>{{AddonSidebar()}}</font></font></div>
+
+<p><font><font>该</font></font><code>Session</code><font><font>对象表示用户在当前浏览会话中已关闭的选项卡或窗口。</font></font></p>
+
+<p><font><font>如果关闭了选项卡但未关闭其窗口,则会话以{{WebExtAPIRef("tabs.Tab", "Tab")}}对象表示:例如,因为用户单击了“关闭选项卡”按钮,并且此选项卡不是其窗口中的唯一选项卡。</font></font></p>
+
+<p><font><font>如果关闭窗口,则会话表示为{{WebExtAPIRef("windows.Window", "Window")}}对象:例如,由于用户单击“关闭窗口”按钮,或关闭了窗口中唯一打开的选项卡。</font></font></p>
+
+<p><font><font>请注意,不同的浏览器可能对会话何时为Tab和何时为Window有不同的想法。</font><font>例如:</font></font></p>
+
+<ul>
+ <li><font><font>在Chrome中,如果用户关闭包含多个标签的窗口,则会话将记录为“窗口”。</font><font>如果用户关闭了仅包含一个选项卡的窗口,则该窗口将记录为一个选项卡。</font></font></li>
+ <li><font><font>在Firefox中,如果用户关闭窗口(或该窗口中最后一个选项卡的选项卡),则将会话记录为窗口,如果用户关闭窗口中最后一个选项卡中的选项卡,则将会话记录为一个Tab。</font></font></li>
+</ul>
+
+<p><font><font>打开的选项卡的Tab对象没有</font></font><code>sessionId</code><font><font>。</font><font>关闭选项卡时,它将具有一个</font></font><code>sessionId</code><font><font>但没有选项卡</font></font><code>id</code><font><font>。</font><font>如果恢复了该标签页,它将获得一个新的标签页,</font></font><code>id</code><font><font>并且会丢失</font></font><code>sessionId</code><font><font>。</font></font></p>
+
+<h2 id="类型"><font><font>类型</font></font></h2>
+
+<p><font><font>此类型的值是对象。</font><font>它们包含以下属性:</font></font></p>
+
+<dl class="reference-values">
+ <dt><code>lastModified</code></dt>
+ <dd><code>number</code><font><font>。</font><font>选项卡或窗口关闭的时间,</font></font><a href="https://en.wikipedia.org/wiki/Unix_time"><font><font>自epoch以来的毫秒数</font></font></a><font><font>。</font></font></dd>
+ <dt><code>tab</code><font><font>{{optional_inline}}</font></font></dt>
+ <dd><code>object</code><font><font>。</font><font>如果对象表示关闭的选项卡,则此属性存在,并且将是{{WebExtAPIRef("tabs.Tab")}}对象。</font><font>仅当扩展名具有“ tabs” </font><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions"><font>许可</font></a><font>权时</font></font><code>url</code><font><font>,</font><font>它才会包含</font></font><code>title</code><font><font>和</font><font>。</font></font><code>favIconUrl</code></dd>
+ <dt><code>window</code><font><font>{{optional_inline}}</font></font></dt>
+ <dd><code>object</code><font><font>。</font><font>如果对象表示一个关闭的窗口,则此属性存在并且将是{{WebExtAPIRef("windows.Window")}}对象。</font></font></dd>
+</dl>
+
+<h2 id="浏览器兼容性"><font><font>浏览器兼容性</font></font></h2>
+
+<p class="hidden"><font><font>此页面中的兼容性表是根据结构化数据生成的。</font><font>如果您想提供数据,请查看</font></font><a href="https://github.com/mdn/browser-compat-data"><font><font>https://github.com/mdn/browser-compat-data</font></font></a><font><font>并向我们​​发送请求请求。</font></font></p>
+
+<p><font><font>{{Compat("webextensions.api.sessions.Session")}}</font></font></p>
+
+<div class="note"><strong><font><font>致谢</font></font></strong>
+
+<p><font><font>该API基于Chromium的</font></font><a href="https://developer.chrome.com/extensions/sessions"><code>chrome.sessions</code></a><font><font>API。</font></font></p>
+
+<p><font><font>Microsoft Edge兼容性数据由Microsoft Corporation提供,并在此处包含在Creative Commons Attribution 3.0美国许可证下。</font></font></p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate"><font><font>//版权所有2015 The Chromium Authors。</font><font>版权所有。</font></font><font><font>
+//</font></font><font><font>
+//以或不以源代码和二进制格式重新分发和使用</font></font><font><font>
+//修改,只要满足以下条件</font></font><font><font>
+//遇到:</font></font><font><font>
+//</font></font><font><font>
+// *重新分发源代码必须保留上述版权</font></font><font><font>
+//注意,此条件列表和以下免责声明。</font></font><font><font>
+// *二进制形式的重新分发必须重现上述内容</font></font><font><font>
+//版权声明,此条件列表和以下免责声明</font></font><font><font>
+//在随附的文档和/或其他材料中</font></font><font><font>
+//分配。</font></font><font><font>
+// *无论是Google Inc.的名称还是Google Inc.的名称</font></font><font><font>
+//贡献者可用于认可或宣传由</font></font><font><font>
+//此软件未经事先特别书面许可。</font></font><font><font>
+//</font></font><font><font>
+//此软件由版权所有者和贡献者提供</font></font><font><font>
+//“按原样”以及任何明示或暗示的保证,包括但不限于</font></font><font><font>
+//仅限于对产品的适销性和适用性的默示担保</font></font><font><font>
+//不提供特殊用途。</font><font>在任何情况下,版权</font></font><font><font>
+//所有者或贡献者对任何直接,间接,偶然的,</font></font><font><font>
+//特殊,示范性或后果性损害(包括但不包括)</font></font><font><font>
+//仅限于,购买替代商品或服务;</font><font>使用损失,</font></font><font><font>
+//数据或利润;</font><font>或业务中断)</font></font><font><font>
+//责任理论,无论是合同形式,严格责任还是侵权行为</font></font><font><font>
+//(包括疏忽大意或其他原因)出于使用目的的任何方式</font></font><font><font>
+//即使已告知可能发生此类损坏,也可以使用本软件。</font></font>
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/storage/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/storage/index.html
new file mode 100644
index 0000000000..2dc4dd3131
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/storage/index.html
@@ -0,0 +1,103 @@
+---
+title: storage
+slug: Mozilla/Add-ons/WebExtensions/API/storage
+tags:
+ - Add-ons
+ - Extensions
+ - Strorage
+translation_of: Mozilla/Add-ons/WebExtensions/API/storage
+---
+<div>{{AddonSidebar}}</div>
+
+<div>使浏览器扩展能够储存及获取数据,以及监听储存的数据的变化。</div>
+
+<div></div>
+
+<p>此存储系统API基于 <a href="/en-US/docs/Web/API/Web_Storage_API">Web Storage API</a>, 并有少许不同。</p>
+
+<p>为了使用该API,您需要在<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a>文件包含"storage"<a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/manifest.json/permissions">权限</a>。每一个浏览器扩展有自己的储存<font face="Consolas, Liberation Mono, Courier, monospace">区域</font>,每一个储存<font face="Consolas, Liberation Mono, Courier, monospace">区域</font>又分为几种不同的存储类型。</p>
+
+<p>虽然此API类似于{{domxref("Window.localStorage")}},但仍建议您不要在插件中使用<code>Window.localStorage。当用户由于隐私原因清除历史浏览记录及数据时,火狐会将在浏览器扩展使用</code> localStorage API存储的数据一并清除。而使用 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/local">storage.local</a>API存储的数据将会恰当保留。</code></p>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("storage.StorageArea")}}</dt>
+ <dd>代表存储<font face="Consolas, Liberation Mono, Courier, monospace">区域</font>的对象</dd>
+ <dt>{{WebExtAPIRef("storage.StorageChange")}}</dt>
+ <dd>代表改变一个储存<font face="Consolas, Liberation Mono, Courier, monospace">区域</font>的对象</dd>
+</dl>
+
+<h2 id="属性">属性</h2>
+
+<p><font face="Consolas, Liberation Mono, Courier, monospace">storage有3个属性,每一个代表不同的存储区域。</font></p>
+
+<dl>
+ <dt>{{WebExtAPIRef("storage.sync")}}</dt>
+ <dd>表示一个同步的储存区域。在此区域的数据通过浏览器进行同步,用户可通过登录使用不同的设备访问到浏览器所有可用的实例对象。</dd>
+ <dt>{{WebExtAPIRef("storage.local")}}</dt>
+ <dd>表示一个本地的存储区域。此区域的数据属于其所在的插件。</dd>
+ <dt>{{WebExtAPIRef("storage.managed")}}</dt>
+ <dd>表示管理的存储区域。此区域的数据由本域名下的管理员设置且对该插件是只读的。试图修改此区域数据会得到一个错误。</dd>
+</dl>
+
+<h2 id="事件">事件</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("storage.onChanged")}}</dt>
+ <dd>当storage有数据变化时,此事件将被触发。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.storage")}}</p>
+
+<div class="hidden note">
+<p>"Chrome不兼容"这部分来源于 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> 使用<a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p>
+
+<p>如果需要更新这部分,请编辑 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, 然后刷新页面即可看见所做更改。</p>
+</div>
+
+<h3 id="在Edge中的不兼容">在Edge中的不兼容</h3>
+
+<p>Promises在Edge中不被支持,使用callbacks代替。</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>这个API基于Chromium的 <a href="https://developer.chrome.com/extensions/storage"><code>chrome.storage</code></a> API. 这篇文档也来源于Chromium 代码中的 <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/storage.json"><code>storage.json</code></a>.</p>
+
+<p>Microsoft Edge的适配数据由Microsoft Corporation提供并且被包含在Creative Commons Attribution 3.0 United States License许可证下.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/create/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/create/index.html
new file mode 100644
index 0000000000..82921cc3ea
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/create/index.html
@@ -0,0 +1,137 @@
+---
+title: tabs.create()
+slug: Mozilla/Add-ons/WebExtensions/API/tabs/create
+tags:
+ - API
+ - 扩展
+ - 方法
+ - 标签页
+ - 页面扩展
+translation_of: Mozilla/Add-ons/WebExtensions/API/tabs/create
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>新建一个 tab.</p>
+
+<p>这是一个异步函数,返回 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>.</p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">var creating = browser.tabs.create(
+ createProperties // object
+)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>createProperties</code></dt>
+ <dd><code>object</code>. Properties to give the new tab. To learn more about these properties, see the {{WebExtAPIRef("tabs.Tab")}} documentation.</dd>
+ <dd>
+ <dl class="reference-values">
+ <dt><code>active</code>{{optional_inline}}</dt>
+ <dd><code>boolean</code>. Whether the tab should become the active tab in the window. Does not affect whether the window is focused (see {{WebExtAPIRef('windows.update')}}). Defaults to <code>true</code>.</dd>
+ <dt><code>cookieStoreId</code> {{optional_inline}}</dt>
+ <dd><code>string</code>. Use this to create a tab whose cookie store ID is <code>cookieStoreId</code>. This option is only available if the extension has the <code>"cookies"</code> <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>.</dd>
+ <dt><code>index</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. The position the tab should take in the window. The provided value will be clamped to between zero and the number of tabs in the window.</dd>
+ <dt><code>openerTabId</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. The ID of the tab that opened this tab. If specified, the opener tab must be in the same window as the newly created tab.</dd>
+ <dt><code>openInReaderMode</code>{{optional_inline}}</dt>
+ <dd><code>boolean</code>. If <code>true</code>, open this tab in <a href="/en-US/Add-ons/WebExtensions/API/tabs/toggleReaderMode">Reader Mode</a>. Defaults to <code>false</code>.</dd>
+ <dt><code>pinned</code>{{optional_inline}}</dt>
+ <dd><code>boolean</code>. Whether the tab should be pinned. Defaults to <code>false</code>.</dd>
+ <dt><code>selected</code>{{optional_inline}}</dt>
+ <dd><code>boolean</code>. Whether the tab should become the selected tab in the window. Defaults to <code>true</code>.
+ <div class="warning">This property is deprecated, and is not supported in Firefox. Use <code>active</code> instead.</div>
+ </dd>
+ <dt><code>url</code>{{optional_inline}}</dt>
+ <dd><code>string</code>. The URL to navigate the tab to initially. Defaults to the New Tab Page.</dd>
+ <dd>Fully-qualified URLs must include a scheme (i.e. 'http://www.google.com', not 'www.google.com').</dd>
+ <dd>For security reasons, in Firefox, this may not be a privileged URL. So passing any of the following URLs will fail:</dd>
+ <dd>
+ <ul>
+ <li>chrome: URLs</li>
+ <li>javascript: URLs</li>
+ <li>data: URLs</li>
+ <li>file: URLs (i.e., files on the filesystem. However, to use a file packaged inside the extension, see below)</li>
+ <li>privileged about: URLs (for example, <code>about:config</code>, <code>about:addons</code>, <code>about:debugging</code>)<span style="display: none;"> </span>. Non-privileged URLs (e.g., <code>about:blank</code>) are allowed.</li>
+ <li>The New Tab page (<code>about:newtab</code>) can be opened if no value for URL is provided.</li>
+ </ul>
+
+ <p>To load a page that's packaged with your extension, specify an absolute URL starting at the extension's manifest.json file. For example: '/path/to/my-page.html'. If you omit the leading '/', the URL is treated as a relative URL, and different browsers may construct different absolute URLs.</p>
+ </dd>
+ <dt><code>windowId</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. The window to create the new tab in. Defaults to the current window.</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h3 id="返回值">返回值</h3>
+
+<p>A <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> that will be fulfilled with a {{WebExtAPIRef('tabs.Tab')}} object containing details about the created tab. If the tab could not be created (for example, because <code>url</code> used a privileged scheme) the promise will be rejected with an error message.</p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.tabs.create", 10)}}</p>
+
+<h2 id="实例">实例</h2>
+
+<p>在新标签页打开 "https://example.org" :</p>
+
+<pre class="brush: js">function onCreated(tab) {
+ console.log(`Created new tab: ${tab.id}`)
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+browser.browserAction.onClicked.addListener(function() {
+ var creating = browser.tabs.create({
+ url:"https://example.org"
+ });
+ creating.then(onCreated, onError);
+});</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/tabs#method-create"><code>chrome.tabs</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/tabs.json"><code>tabs.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/discard/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/discard/index.html
new file mode 100644
index 0000000000..d988e6682d
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/discard/index.html
@@ -0,0 +1,108 @@
+---
+title: tabs.discard()
+slug: Mozilla/Add-ons/WebExtensions/API/tabs/discard
+translation_of: Mozilla/Add-ons/WebExtensions/API/tabs/discard
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>丢弃一个或多个标签页。</p>
+
+<p>一些浏览器会自动“丢弃”它们认为近期不再被用户所需要的标签页。这些标签页会在标签栏中保持可见,浏览器会记住它们的状态,所以,如果用户选中了被丢弃的标签页,它会立即还原到被丢弃之前的状态。</p>
+
+<p>对于不同的浏览器,被丢弃内容的详细内容是有所不同的,但是从大体上来说,丢弃一个标签页允许浏览器释放一些该标签页所占用的内存。</p>
+
+<p>The {{WebExtAPIRef("tabs.discard()")}} API enables an extension to discard one or more tabs. It's not possible to discard the currently active tab, or a tab whose document contains a <code><a href="/en-US/docs/Web/Events/beforeunload">beforeunload</a></code> listener that would display a prompt.</p>
+
+<p>This is an asynchronous function that returns a <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>.</p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">var discarding = browser.tabs.discard(
+ tabIds // integer or integer array
+)
+</pre>
+
+<h3 id="Parameters">Parameters</h3>
+
+<dl>
+ <dt><code>tabIds</code></dt>
+ <dd><code><code>integer</code></code> or <code><code>array</code></code> of <code><code><code>integer</code></code></code>. The IDs of the tab or tabs to discard.</dd>
+</dl>
+
+<h3 id="Return_value">Return value</h3>
+
+<p>A <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> that will be fulfilled with no arguments when all the specified tabs have been discarded. If any error occurs (for example, invalid tab IDs), the promise will be rejected with an error message.</p>
+
+<p>If the ID of the active tab is passed in, it will not be discarded, but the promise will be fulfilled and any other tabs passed in will be discarded.</p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.tabs.discard", 10)}}</p>
+
+<h2 id="示例">示例</h2>
+
+<p>丢弃一个标签页:</p>
+
+<pre class="brush: js">function onDiscarded() {
+ console.log(`Discarded`);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+var discarding = browser.tabs.discard(2);
+discarding.then(onDiscarded, onError);</pre>
+
+<p>丢弃多个标签页:</p>
+
+<pre class="brush: js">function onDiscarded() {
+ console.log(`Discarded`);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+var discarding = browser.tabs.discard([15, 14, 1]);
+discarding.then(onDiscarded, onError);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/tabs#method-discard"><code>chrome.tabs</code></a> API.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/executescript/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/executescript/index.html
new file mode 100644
index 0000000000..f32dd6cfc6
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/executescript/index.html
@@ -0,0 +1,173 @@
+---
+title: tabs.executeScript()
+slug: Mozilla/Add-ons/WebExtensions/API/tabs/executeScript
+tags:
+ - Chrome Extensions
+ - Extensions
+ - Plugins
+ - WebExtensions
+ - executeScript
+ - tabs.executeScript()
+translation_of: Mozilla/Add-ons/WebExtensions/API/tabs/executeScript
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>将 JavaScript 代码注入页面。</p>
+
+<p>You can inject code into pages whose URL can be expressed using a <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns">match pattern</a>: meaning, its scheme must be one of "http", "https", "file", "ftp". To do this you must have the permission for the page's URL, either explicitly as a <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">host permission</a>, or via the <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission">activeTab permission</a>.</p>
+
+<p>You can also inject code into pages packaged with your own extension:</p>
+
+<pre class="brush: js">browser.tabs.create({url: "/my-page.html"}).then(() =&gt; {
+ browser.tabs.executeScript({
+ code: `console.log('location:', window.location.href);`
+ });
+});</pre>
+
+<p>You don't need any special permissions to do this.</p>
+
+<p>You <em>can't</em> inject code into any of the browser's built-in pages, such as about:debugging, about:addons, or the page that opens when you open a new empty tab.</p>
+
+<p>The scripts you inject are called content scripts. <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">Learn more about content scripts</a>.</p>
+
+<p>This is an asynchronous function that returns a <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>.</p>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js">var executing = browser.tabs.executeScript(
+ tabId, // optional integer
+ details // object
+)
+</pre>
+
+<h3 id="Parameters">Parameters</h3>
+
+<dl>
+ <dt><code>tabId</code> {{optional_inline}}</dt>
+ <dd><code>integer</code>. The ID of the tab in which to run the script. Defaults to the active tab of the current window.</dd>
+ <dt><code>details</code></dt>
+ <dd>An object describing the script to run. It contains the following properties:</dd>
+ <dd>
+ <dl class="reference-values">
+ <dt><code>allFrames</code> {{optional_inline}}</dt>
+ <dd><code>boolean</code>. If <code>true</code>, the code will be injected into all frames of the current page. If <code>true</code> and <code>frameId</code> is set, then it will raise an error,  frameId and allFrames are mutually exclusive. If it is <code>false</code>, code is only injected into the top frame. Defaults to <code>false</code>.</dd>
+ <dt><code>code</code> {{optional_inline}}</dt>
+ <dd><code>string</code>. Code to inject, as a text string. <strong>Warning:</strong> Don’t use this property to interpolate untrusted data into JavaScript, as this could lead to a security issue.</dd>
+ <dt><code>file</code> {{optional_inline}}</dt>
+ <dd><code>string</code>. Path to a file containing the code to inject. In Firefox, relative URLs not starting at the extension root are resolved relative to the current page URL. In Chrome, these URLs are resolved relative to the extension's base URL. To work cross-browser, you can specify the path as a relative URL, starting at the extension's root, like this: <code>"/path/to/script.js"</code>.</dd>
+ <dt><code>frameId</code> {{optional_inline}}</dt>
+ <dd><code>integer</code>. The frame where the code should be injected. Defaults to <code>0</code> (the top-level frame).</dd>
+ <dt><code>matchAboutBlank</code> {{optional_inline}}</dt>
+ <dd><code>boolean</code>. If <code>true</code>, the code will be injected into embedded "about:blank" and "about:srcdoc" frames if your extension has access to their parent document. The code cannot be inserted in top-level about: frames. Defaults to <code>false</code>.</dd>
+ <dt><code>runAt</code> {{optional_inline}}</dt>
+ <dd>{{WebExtAPIRef('extensionTypes.RunAt')}}. The soonest that the code will be injected into the tab. Defaults to "document_idle".</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h3 id="Return_value">Return value</h3>
+
+<p>A <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> that will be fulfilled with an array of objects, representing the result of the script in every injected frame.</p>
+
+<p>The result of the script is the last evaluated statement, which is similar to what would be output (the results, not any <code>console.log()</code> output) if you executed the script in the <a href="/en-US/docs/Tools/Web_Console">Web Console</a>. For example, consider a script like this:</p>
+
+<pre class="brush: js">var foo='my result';foo;</pre>
+
+<p>Here the results array will contain the the string "<code>my result</code>" as an element. The result values must be <a href="/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm">structured clonable</a>.</p>
+
+<p>If any error occurs the promise will be rejected with an error message.</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.tabs.executeScript")}}</p>
+
+<h2 id="Examples">Examples</h2>
+
+<p>This example executes a one-line code snippet in the currently active tab:</p>
+
+<pre class="brush: js">function onExecuted(result) {
+ console.log(`We made it green`);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+var makeItGreen = 'document.body.style.border = "5px solid green"';
+
+var executing = browser.tabs.executeScript({
+ code: makeItGreen
+});
+executing.then(onExecuted, onError);</pre>
+
+<p>This example executes a script from a file, packaged with the extension, called "content-script.js". The script is executed in the currently active tab. The script is executed in subframes as well as the main document:</p>
+
+<pre class="brush: js">function onExecuted(result) {
+ console.log(`We executed in all subframes`);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+var executing = browser.tabs.executeScript({
+ file: "/content-script.js",
+ allFrames: true
+});
+executing.then(onExecuted, onError);</pre>
+
+<p>This example executes a script from a file, packaged with the extension, called "content-script.js". The script is executed in the tab with an ID of 2:</p>
+
+<pre class="brush: js">function onExecuted(result) {
+ console.log(`We executed in tab 2`);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+var executing = browser.tabs.executeScript(
+ 2, {
+ file: "/content-script.js"
+});
+executing.then(onExecuted, onError);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/tabs#method-executeScript"><code>chrome.tabs</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/tabs.json"><code>tabs.json</code></a> in the Chromium code.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/index.html
new file mode 100644
index 0000000000..868b3e1238
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/index.html
@@ -0,0 +1,192 @@
+---
+title: tabs
+slug: Mozilla/Add-ons/WebExtensions/API/tabs
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - Interface
+ - NeedsTranslation
+ - Non-standard
+ - Reference
+ - TopicStub
+ - WebExtensions
+ - tabs
+translation_of: Mozilla/Add-ons/WebExtensions/API/tabs
+---
+<div>{{AddonSidebar}}</div>
+
+<p>与浏览器标签系统进行交互。</p>
+
+<p>你可以使用该API获取一个已打开标签的列表并且使用各种标准过滤标签,并进行 打开, 刷新,移动,重载,移除操作。该API不能直接访问标签中的主机内容,但是你可以使用 {{WebExtAPIRef("tabs.executeScript()")}} 或者 {{WebExtAPIRef("tabs.insertCSS()")}} APIs,来插入javascript和CSS。</p>
+
+<p>你可以在不需要任何特殊权限的情况下使用该APIS的大部分, 除了:</p>
+
+<ul>
+ <li>获取 <code>Tab.url</code>, <code>Tab.title</code>, and <code>Tab.favIconUrl</code>, 你需要拥有 "tabs" <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a>. 在火狐,这也意味着你需要 "tabs" ,来通过URL使用 {{WebExtAPIRef("tabs.query", "query")}}。</li>
+ <li>使用 {{WebExtAPIRef("tabs.executeScript()")}} 或者 {{WebExtAPIRef("tabs.insertCSS()")}} 你必须在目标标签拥有 <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">host permission</a> 。</li>
+</ul>
+
+<p>或者你可以仅仅只为当前的活动标签临时的获取这些权限并且仅仅只响应一个显示的用户行为,请查看 <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission">"activeTab" permission</a>.</p>
+
+<h2 id="枚举值">枚举值</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("tabs.MutedInfoReason")}}</dt>
+ <dd>确定一个标签静音与否的原因(用户修改,扩展修改)。</dd>
+ <dt>{{WebExtAPIRef("tabs.MutedInfo")}}</dt>
+ <dd>该对象包含一个布尔值只是该标签是否静音,以及最近一次静音的原因。</dd>
+ <dt>{{WebExtAPIRef("tabs.Tab")}}</dt>
+ <dd>该值包含了一个标签的信息。</dd>
+ <dt>{{WebExtAPIRef("tabs.TabStatus")}}</dt>
+ <dd>指示某个标签是否已经加载完成</dd>
+ <dt>{{WebExtAPIRef("tabs.WindowType")}}</dt>
+ <dd>包含该标签的窗口类型。</dd>
+ <dt>{{WebExtAPIRef("tabs.ZoomSettingsMode")}}</dt>
+ <dd>定义缩放由浏览器控制或是扩展,或者禁用。</dd>
+ <dt>{{WebExtAPIRef("tabs.ZoomSettingsScope")}}</dt>
+ <dd>定义缩放将对某个网址持续生效,或者仅仅只针对该标签。</dd>
+ <dt>{{WebExtAPIRef("tabs.ZoomSettings")}}</dt>
+ <dd>定义缩放设置。 {{WebExtAPIRef("tabs.ZoomSettingsMode", "mode")}}, {{WebExtAPIRef("tabs.ZoomSettingsScope", "scope")}}, 和默认缩放比例。</dd>
+</dl>
+
+<h2 id="属性">属性</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("tabs.TAB_ID_NONE")}}</dt>
+ <dd>给予非浏览器标签的一个特殊ID值 (比如,在开发工具中的标签)。</dd>
+</dl>
+
+<h2 id="方法">方法</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("tabs.connect()")}}</dt>
+ <dd>在运行于该标签的任何 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">content scripts </a> 和该扩展的后台脚本(或者其他的比如弹出菜单脚本或者设置页面脚本)间创建一个消息连接。</dd>
+ <dt>{{WebExtAPIRef("tabs.create()")}}</dt>
+ <dd>创建一个新标签。</dd>
+ <dt>{{WebExtAPIRef("tabs.captureVisibleTab()")}}</dt>
+ <dd>创意一个数据统一资源标识符解码在规定窗口中当前活动标签的可视区域重的一个图片。</dd>
+ <dt>{{WebExtAPIRef("tabs.detectLanguage()")}}</dt>
+ <dd>检查在一个标签中的主要语言。</dd>
+ <dt>{{WebExtAPIRef("tabs.duplicate()")}}</dt>
+ <dd>复制一个标签</dd>
+ <dt>{{WebExtAPIRef("tabs.executeScript()")}}</dt>
+ <dd>向一个页面注入脚本。</dd>
+ <dt>{{WebExtAPIRef("tabs.get()")}}</dt>
+ <dd>取回制定标签的详细信息。</dd>
+ <dt>{{WebExtAPIRef("tabs.getAllInWindow()")}} {{deprecated_inline}}</dt>
+ <dd>获取指定窗口所有标签的详细信息。</dd>
+ <dt>{{WebExtAPIRef("tabs.getCurrent()")}}</dt>
+ <dd>返回一个 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/Tabs/Tab" title="This type contains information about a tab."><code>tabs.Tab</code></a> 对象包含了该脚本当前的宿主标签的信息。</dd>
+ <dt>{{WebExtAPIRef("tabs.getSelected()")}} {{deprecated_inline}}</dt>
+ <dd>获取在指定窗口被选定的标签。</dd>
+ <dt>{{WebExtAPIRef("tabs.getZoom()")}}</dt>
+ <dd>获取制定标签的缩放系数。</dd>
+ <dt>{{WebExtAPIRef("tabs.getZoomSettings()")}}</dt>
+ <dd>获取指定标签的缩放设置。</dd>
+ <dt>{{WebExtAPIRef("tabs.highlight()")}}</dt>
+ <dd>高亮显示一个或多个标签。</dd>
+ <dt>{{WebExtAPIRef("tabs.insertCSS()")}}</dt>
+ <dd>向一个页面注入CSS。</dd>
+ <dt>{{WebExtAPIRef("tabs.removeCSS()")}}</dt>
+ <dd>移除之前调用{{WebExtAPIRef("tabs.insertCSS()")}} 注入的一个css。</dd>
+ <dt>{{WebExtAPIRef("tabs.move()")}}</dt>
+ <dd>移动一个或多个标签页到同一窗口的一个新的位置或是到不同窗口。</dd>
+ <dt>{{WebExtAPIRef("tabs.query()")}}</dt>
+ <dd>获取所有包含指定属性的标签,如果没有属性则获取所有标签。</dd>
+ <dt>{{WebExtAPIRef("tabs.reload()")}}</dt>
+ <dd>重在一个标签,可选的可以绕过本地缓存。</dd>
+ <dt>{{WebExtAPIRef("tabs.remove()")}}</dt>
+ <dd>关闭一个或多个标签。</dd>
+ <dt>{{WebExtAPIRef("tabs.sendMessage()")}}</dt>
+ <dd>向一个指定标签的content script 发送单个消息。</dd>
+ <dt>{{WebExtAPIRef("tabs.sendRequest()")}} {{deprecated_inline}}</dt>
+ <dd>向一个指定标签的content script 发送一个单一请求。 <strong>过时</strong>: 请使用 {{WebExtAPIRef("tabs.sendMessage()")}} 替代。</dd>
+ <dt>{{WebExtAPIRef("tabs.setZoom()")}}</dt>
+ <dd>缩放指定标签。</dd>
+ <dt>{{WebExtAPIRef("tabs.setZoomSettings()")}}</dt>
+ <dd>为一个制定标签设置缩放选项。</dd>
+ <dt>{{WebExtAPIRef("tabs.update()")}}</dt>
+ <dd>导航一个标签到新的地址,或是修改其它的属性。</dd>
+</dl>
+
+<h2 id="Events">Events</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("tabs.onActivated")}}</dt>
+ <dd>当窗口活动标签改变时触发,注意当该消息触发时,标签地址可能没有被设置。</dd>
+ <dt>{{WebExtAPIRef("tabs.onActiveChanged")}} {{deprecated_inline}}</dt>
+ <dd> <strong>已过时:</strong> 请使用 {{WebExtAPIRef("tabs.onActivated")}} 代替。</dd>
+ <dt>{{WebExtAPIRef("tabs.onAttached")}}</dt>
+ <dd>当一个标签被附加到一个窗口时触发,因为他可能在窗口间移动。</dd>
+ <dt>{{WebExtAPIRef("tabs.onCreated")}}</dt>
+ <dd>当一个标签被创建时触发,注意当该事件触发时可能没有设置地址。</dd>
+ <dt>{{WebExtAPIRef("tabs.onDetached")}}</dt>
+ <dd>当一个标签脱离一个窗口时被触发。</dd>
+ <dt>{{WebExtAPIRef("tabs.onHighlightChanged")}} {{deprecated_inline}}</dt>
+ <dd><strong>过时:</strong> 请使用 {{WebExtAPIRef("tabs.onHighlighted")}} 代替。</dd>
+ <dt>{{WebExtAPIRef("tabs.onHighlighted")}}</dt>
+ <dd>当一个标签被高亮显示或是被选中时触发。</dd>
+ <dt>{{WebExtAPIRef("tabs.onMoved")}}</dt>
+ <dd>当一个标签在一个窗口内移动时被触发。</dd>
+ <dt>{{WebExtAPIRef("tabs.onRemoved")}}</dt>
+ <dd>当一个标签关闭时被处罚。</dd>
+ <dt>{{WebExtAPIRef("tabs.onReplaced")}}</dt>
+ <dd>当一个标签因为预载取代另一个标签时被触发。</dd>
+ <dt>{{WebExtAPIRef("tabs.onSelectionChanged")}} {{deprecated_inline}}</dt>
+ <dd> <strong>以过时:</strong> 请使用 {{WebExtAPIRef("tabs.onActivated")}} 代替。</dd>
+ <dt>{{WebExtAPIRef("tabs.onUpdated")}}</dt>
+ <dd>当一个标签被更新时触发。</dd>
+ <dt>{{WebExtAPIRef("tabs.onZoomChange")}}</dt>
+ <dd>当一个标签被缩放时触发</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.tabs")}}</p>
+
+<div class="hidden note">
+<p>The "Chrome incompatibilities" section is included from <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> using the <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p>
+
+<p>If you need to update this content, edit <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, then shift-refresh this page to see your changes.</p>
+</div>
+
+<p> {{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/tabs"><code>chrome.tabs</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/tabs.json"><code>tabs.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/insertcss/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/insertcss/index.html
new file mode 100644
index 0000000000..5ea7d5205c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/insertcss/index.html
@@ -0,0 +1,129 @@
+---
+title: tabs.insertCSS()
+slug: Mozilla/Add-ons/WebExtensions/API/tabs/insertCSS
+tags:
+ - 注入CSS
+translation_of: Mozilla/Add-ons/WebExtensions/API/tabs/insertCSS
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>向一个页面注入CSS</p>
+
+<p>使用该API前你必须拥有目标页面的权限, 可以是 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">主机权限</a>, 或者使用 <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission">activeTab 权限</a>.</p>
+
+<p>你只能向符合 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns">match pattern </a>的网页注入CSS: 其形式必定是 "http", "https", "file", "ftp" 之一. 你不能向任何浏览器内置页面注入CSS, 比如 about:debugging, about:addons, 或者你打开的一个新的空白页。</p>
+
+<p>当再次调用{{WebExtAPIRef("tabs.removeCSS()")}} 时,已经注入的CSS可能会被清除。</p>
+
+<p>这是一个返回<code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> 的异步函数。</p>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js">var inserting = browser.tabs.insertCSS(
+ tabId, // optional integer
+ details // extensionTypes.InjectDetails
+)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>tabId</code> {{optional_inline}}</dt>
+ <dd><code>integer,</code> 将要注入css的标签ID。默认为当前窗口的活动标签。</dd>
+ <dt><code>details</code></dt>
+ <dd>{{WebExtAPIRef('extensionTypes.InjectDetails')}}. 对注入的描述,包含以下属性:</dd>
+ <dd>
+ <dl class="reference-values">
+ <dt><code>allFrames</code>{{optional_inline}}</dt>
+ <dd><code>boolean</code>. 如果为真,该CSS会被注入到该页面的所有框架,如果为假,Css只会注入到最顶层框架,默认为假。</dd>
+ <dt><code>code</code>{{optional_inline}}</dt>
+ <dd><code>string</code>. 将要注入的代码。</dd>
+ <dt><code>file</code>{{optional_inline}}</dt>
+ <dd><code>string</code>. 包含将要注入代码的文件路径,在Firefox中,相对URLs 决定于当前页面的URL,在Chrome中,决定于扩展的基础URL。为了跨浏览器工作,你应该使用一个从扩展根目录开始的绝对路径,比如 : <code>"/path/to/stylesheet.css"</code>.</dd>
+ <dt><code>frameId</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. CSS应该被注入的框架. 默认为 <code>0</code> (顶层框架).</dd>
+ <dt><code>matchAboutBlank</code>{{optional_inline}}</dt>
+ <dd><code>boolean</code>. If <code>true</code>, the code will be injected into embedded "about:blank" and "about:srcdoc" frames if your add-on has access to their parent document. The code cannot be inserted in top-level about: frames. Defaults to <code>false</code>.</dd>
+ <dt><code>runAt</code>{{optional_inline}}</dt>
+ <dd>{{WebExtAPIRef('extensionTypes.RunAt')}}. The soonest that the code will be injected into the tab. Defaults to "document_idle".</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h3 id="Return_value">Return value</h3>
+
+<p> <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> 将会在CSS成功注入时 被填充,如果有任何错误发生,promise将会被注入一个错误消息。</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.tabs.insertCSS")}}</p>
+
+<h2 id="例子">例子</h2>
+
+<p>下面例子将通过字符串变量形式向当前活动标签注入一段CSS代码</p>
+
+<pre class="brush: js">var css = "body { border: 20px dotted pink; }";
+
+browser.browserAction.onClicked.addListener(() =&gt; {
+
+ function onError(error) {
+ console.log(`Error: ${error}`);
+ }
+
+ var insertingCSS = browser.tabs.insertCSS({code: css});
+ insertingCSS.then(null, onError);
+});</pre>
+
+<p>下面例子将以通过加载文件形式向页面注入CSS。CSS被注入在ID为2的tab中。</p>
+
+<pre class="brush: js">browser.browserAction.onClicked.addListener(() =&gt; {
+
+ function onError(error) {
+ console.log(`Error: ${error}`);
+ }
+
+ var insertingCSS = browser.tabs.insertCSS(2, {file: "content-style.css"});
+ insertingCSS.then(null, onError);
+});</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>致谢</strong>
+
+<p>本页 API 以谷歌 Chromium的 <a href="https://developer.chrome.com/extensions/tabs#method-insertCSS"><code>chrome.tabs</code></a> API为基础. 该篇文档由Chromium 代码 <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/tabs.json"><code>tabs.json</code></a>衍变而来.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/onactivated/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/onactivated/index.html
new file mode 100644
index 0000000000..0ce8758760
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/onactivated/index.html
@@ -0,0 +1,110 @@
+---
+title: tabs.onActivated
+slug: Mozilla/Add-ons/WebExtensions/API/tabs/onActivated
+translation_of: Mozilla/Add-ons/WebExtensions/API/tabs/onActivated
+---
+<div>{{AddonSidebar()}}</div>
+
+<div>当窗体的活动标签变化时触发。请注意事件触发时标签的 URL 可能尚未设置,但是你可以通过监听 {{WebExtAPIRef("tabs.onUpdated")}} 事件在 URL 被设置后得到通知。</div>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">browser.tabs.onActivated.addListener(listener)
+browser.tabs.onActivated.removeListener(listener)
+browser.tabs.onActivated.hasListener(listener)
+</pre>
+
+<p>此事件有三个方法:</p>
+
+<dl>
+ <dt><code>addListener(callback)</code></dt>
+ <dd>向此事件添加一个监听。</dd>
+ <dt><code>removeListener(listener)</code></dt>
+ <dd>停止监听此事件。 <code>listener</code> 参数是将要移除的监听。</dd>
+ <dt><code>hasListener(listener)</code></dt>
+ <dd>检查 <code>listener</code> 是否在此事件中注册。如果正在监听返回 <code>true</code> ,否则 <code>false。</code></dd>
+</dl>
+
+<h2 id="addListener_语法">addListener 语法</h2>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>callback</code></dt>
+ <dd>
+ <p>事件发生时被执行的方法。以下参数会被传递至该方法:</p>
+
+ <dl class="reference-values">
+ <dt><code>activeInfo</code></dt>
+ <dd><a href="#activeInfo"><code>object</code></a>. 被激活标签的ID , 以及它的窗体的 ID 。</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h2 id="额外的对象">额外的对象</h2>
+
+<h3 id="activeInfo">activeInfo</h3>
+
+<dl class="reference-values">
+ <dt><code>tabId</code></dt>
+ <dd><code>integer</code>. 被激活的标签的ID。</dd>
+ <dt><code>windowId</code></dt>
+ <dd><code>integer</code>. 此标签的窗体的ID。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.tabs.onActivated")}}</p>
+
+<h2 id="示例">示例</h2>
+
+<p>监听并记录标签激活事件:</p>
+
+<pre class="brush: js">function handleActivated(activeInfo) {
+ console.log("Tab " + activeInfo.tabId +
+ " was activated");
+}
+
+browser.tabs.onActivated.addListener(handleActivated);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/tabs#event-onActivated"><code>chrome.tabs</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/tabs.json"><code>tabs.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/sendmessage/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/sendmessage/index.html
new file mode 100644
index 0000000000..8e968a2b1b
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/sendmessage/index.html
@@ -0,0 +1,129 @@
+---
+title: tabs.sendMessage()
+slug: Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage
+translation_of: Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>从background scripts中发送单个消息 (or other privileged scripts, such as popup scripts or options page scripts) 到任何content scripts that belong to the extension and are running in the specified tab.</p>
+
+<p>这个消息将被content scripts中 {{WebExtAPIRef("runtime.onMessage")}} 事件的所有监听者收到,然后它们可以选择通过使用 <code>sendResponse</code> 这个方法发送一个response到background scripts。</p>
+
+<p>This is an asynchronous function that returns a <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>.</p>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js">var sending = browser.tabs.sendMessage(
+ tabId, // integer
+ message, // any
+ options // optional object
+)
+</pre>
+
+<h3 id="Parameters">Parameters</h3>
+
+<dl>
+ <dt><code>tabId</code></dt>
+ <dd><code>integer</code>. ID of the tab whose content scripts we want to send a message to.</dd>
+ <dt><code>message</code></dt>
+ <dd><code>any</code>. An object that can be serialized to JSON.</dd>
+ <dt><code>options</code>{{optional_inline}}</dt>
+ <dd><code>object</code>.</dd>
+ <dd>
+ <dl class="reference-values">
+ <dt><code>frameId</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. Sends the message to a specific frame identified by <code>frameId</code> instead of all frames in the tab. Whether the content script is executed in all frames depends on the <code>all_frames</code> setting in the <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/content_scripts"><code>content_scripts</code></a> section of manifest.json.</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h3 id="Return_value">Return value</h3>
+
+<p>A <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> that will be fulfilled with the JSON response object sent by the handler of the message in the content script, or with no arguments if the content script did not send a response. If an error occurs while connecting to the specified tab or any other error occurs, the promise will be rejected with an error message. If several frames response to the message, the promise is resolved to one of answers.</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.tabs.sendMessage")}}</p>
+
+<h2 id="Examples">Examples</h2>
+
+<p>Here's an example of a background script that sends a message to the content scripts running in the active tab when the user clicks the browser action. The background script also expects the content script to send a response:</p>
+
+<pre class="brush: js">// background-script.js
+"use strict";
+
+function onError(error) {
+ console.error(`Error: ${error}`);
+}
+
+function sendMessageToTabs(tabs) {
+ for (let tab of tabs) {
+ browser.tabs.sendMessage(
+ tab.id,
+ {greeting: "Hi from background script"}
+ ).then(response =&gt; {
+ console.log("Message from the content script:");
+ console.log(response.response);
+ }).catch(onError);
+ }
+}
+
+browser.browserAction.onClicked.addListener(() =&gt; {
+ browser.tabs.query({
+ currentWindow: true,
+ active: true
+ }).then(sendMessageToTabs).catch(onError);
+});</pre>
+
+<p>Here's the corresponding content script:</p>
+
+<pre class="brush: js">// content-script.js
+"use strict";
+
+browser.runtime.onMessage.addListener(request =&gt; {
+ console.log("Message from the background script:");
+ console.log(request.greeting);
+ return Promise.resolve({response: "Hi from content script"});
+});</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/tabs#method-sendMessage"><code>chrome.tabs</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/tabs.json"><code>tabs.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/tab/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/tab/index.html
new file mode 100644
index 0000000000..2fed2e8dd7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/tab/index.html
@@ -0,0 +1,117 @@
+---
+title: tabs.Tab
+slug: Mozilla/Add-ons/WebExtensions/API/tabs/Tab
+tags:
+ - 扩展
+ - 标签
+ - 标签页
+ - 类型
+ - 非标准
+ - 页面扩展
+translation_of: Mozilla/Add-ons/WebExtensions/API/tabs/Tab
+---
+<div>{{AddonSidebar()}}</div>
+
+<p> <strong><code>tabs.Tab</code></strong> 包含有关标签页的信息 . 这样可以访问有关标签页中的内容,内容有多大,特殊状态或限制有效的信息等等。</p>
+
+<h2 id="类型">类型</h2>
+
+<p>这种类型的值是对象。它包含以下属性:</p>
+
+<dl class="reference-values">
+ <dt><code>active</code></dt>
+ <dd><code>boolean</code>. 该标签页是否在其窗口中处于活动状态。即使标签的窗口当前没有被关注,也可能是true。</dd>
+ <dt><code>audible</code> {{optional_inline}}</dt>
+ <dd><code>boolean</code>. 如果标签页没有静音:标签页是否正在发出声音。如果标签页被静音:如果没有静音标签页是否会发出声音。</dd>
+ <dt><code>autoDiscardable</code> {{optional_inline}}</dt>
+ <dd><code>boolean</code>. 资源不足时浏览器是否可以自动丢弃该标签页。</dd>
+ <dt><code>cookieStoreId</code> {{optional_inline}}</dt>
+ <dd><code>string</code>. 该标签页的Cookie存储. 如果不同的标签可以有不同的cookie存储 (例如, 支持 <a href="https://wiki.mozilla.org/Security/Contextual_Identity_Project/Containers">contextual identity</a>), you can pass this as the <code>storeId</code> option into various methods of the {{WebExtAPIRef("cookies")}} API, 设置和获取与此标签页的Cookie存储关联的Cookie。 只有在扩展名具有“cookies”<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权</a></dd>
+ <dd><code>string</code>. 该标签页的Cookie存储. 如果不同的标签可以有不同的cookie存储 (例如, 支持 <a href="https://wiki.mozilla.org/Security/Contextual_Identity_Project/Containers">contextual identity</a>), 你可以将此作为 <code>storeId</code> 选项传递给 {{WebExtAPIRef("cookies")}} API的各种方法, 设置和获取与此标签页的Cookie存储关联的Cookie。 只有在扩展具有“cookies”<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a>的情况下才会出现.</dd>
+ <dt><code>discarded</code> {{optional_inline}}</dt>
+ <dd><code>boolean</code>. 是否丢弃的标签页。被丢弃的标签页是其内容已经从内存中卸载的标签页,但在标签页条中仍可见。它的内容在下一次被激活时被重新加载。</dd>
+ <dt><code>favIconUrl</code> {{optional_inline}}</dt>
+ <dd><code>string</code>. 该标签的图标的网址。 只有在扩展具有“cookies”<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a>的情况下才会出现. 如果标签页正在加载中,该值可以为空字符串</dd>
+ <dt><code>height</code> {{optional_inline}}</dt>
+ <dd><code>integer</code>. 标签页的像素单位高度。</dd>
+ <dt><code>highlighted</code></dt>
+ <dd><code>boolean</code>. 标签页是否突出显示。</dd>
+ <dt><code>id</code> {{optional_inline}}</dt>
+ <dd><code>integer</code>. 标签页的ID. 标签 ID在浏览器的会话中是唯一的 。 在浏览器窗口中不包含内容的标签页 (例如, devtools 窗口),标签 ID 也可以设置为 {{WebExtAPIRef('tabs.TAB_ID_NONE')}} 。</dd>
+ <dt><code>incognito</code></dt>
+ <dd><code>boolean</code>. 该标签页是否在隐私浏览窗口中。</dd>
+ <dt><code>index</code></dt>
+ <dd><code>integer</code>. 窗口中的标签页从零开始的索引。</dd>
+ <dt><code>isArticle</code></dt>
+ <dd><code>boolean</code>. 如果标签页可以在<a href="/en-US/Add-ons/WebExtensions/API/tabs/toggleReaderMode"> Reader模式下呈现</a>,则返回true,否则返回false。</dd>
+ <dt><code>isInReaderMode</code></dt>
+ <dd><code>boolean</code>. 如果标签页正在<a href="/en-US/Add-ons/WebExtensions/API/tabs/toggleReaderMode"> Reader模式下呈现</a>,则返回true,否则返回false。</dd>
+ <dt><code>lastAccessed</code></dt>
+ <dd><code>double</code>. 上次访问该标签页的时间 , 参考 <a class="external external-icon" href="https://en.wikipedia.org/wiki/Unix_time">milliseconds since the epoch</a>.</dd>
+ <dt><code>mutedInfo</code> {{optional_inline}}</dt>
+ <dd>{{WebExtAPIRef('tabs.MutedInfo')}}.标签页的当前静音状态以及上次状态更改的原因。</dd>
+ <dt><code>openerTabId</code> {{optional_inline}}</dt>
+ <dd><code>integer</code>. 打开此标签页的标签页ID(如果有)。如果开启者标签页仍然存在,该属性才会出现。</dd>
+ <dt><code>pinned</code></dt>
+ <dd><code>boolean</code>. 标签页是否被固定</dd>
+ <dt><code>selected</code> {{deprecated_inline}}</dt>
+ <dd><code>boolean</code>.标签页是否被选中</dd>
+ <dt><code>sessionId</code> {{optional_inline}}</dt>
+ <dd><code>string</code>. 从{{WebExtAPIRef('sessions')}} API 获取的标签页的唯一标识会话ID.</dd>
+ <dt><code>status</code> {{optional_inline}}</dt>
+ <dd><code>string</code>.<em>加载</em> 或 <em>完成</em>.</dd>
+ <dt><code>title</code> {{optional_inline}}</dt>
+ <dd><code>string</code>. 标签页的标题. 只有当扩展具有 <code>"tabs"</code> <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a> 时才会出现.</dd>
+ <dt><code>url</code> {{optional_inline}}</dt>
+ <dd><code>string</code>. 该选项卡正在显示的文档的URL。只有当扩展具有 <code>"tabs"</code> <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a> 时才会出现.</dd>
+ <dt><code>width</code> {{optional_inline}}</dt>
+ <dd><code>integer</code>. 标签页的像素单位宽度。</dd>
+ <dt><code>windowId</code></dt>
+ <dd><code>integer</code>. 包含此标签页的窗口ID。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.tabs.Tab", 10)}}</p>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>感谢</strong>
+
+<p>此 API 基于 Chromium的 <a href="https://developer.chrome.com/extensions/tabs#type-Tab"><code>chrome.tabs</code></a> API. 本文档来源于Chromium 代码中的 <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/tabs.json"><code>tabs.json</code></a>.</p>
+
+<p>Microsoft Edge兼容性数据由Microsoft Corporation提供,并包含在Creative Commons Attribution 3.0美国许可证下。</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/查询/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/查询/index.html
new file mode 100644
index 0000000000..9afe6e80a8
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/tabs/查询/index.html
@@ -0,0 +1,179 @@
+---
+title: 选项卡. 查询 ()
+slug: Mozilla/Add-ons/WebExtensions/API/tabs/查询
+translation_of: Mozilla/Add-ons/WebExtensions/API/tabs/query
+---
+<div>[阿登侧边栏()]</div>
+
+<p>获取具有指定属性的所有选项卡,如果未指定任何属性,则获取所有选项卡。</p>
+
+<p><font>这是返回 的异步函数。</font><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code></p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js notranslate">let querying = browser.tabs.query(<var>queryObj</var>)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code><var>queryObj</var></code></dt>
+ <dd>
+ <p><code>object</code><font>.函数将仅获取其属性与此处包含的属性匹配的选项卡。</font><code>query()</code></p>
+
+ <p>请参阅 \WebExtAPIRef("选项卡")。Tab")=文档以了解有关这些属性的详细信息。</p>
+
+ <dl class="reference-values">
+ <dt><code>active</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.选项卡是否在窗口中处于活动状态。</font></dd>
+ <dt><code>audible</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.标签是否可听见。</font></dd>
+ <dt><code>autoDiscardable</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.当资源不足时,浏览器是否可以自动丢弃选项卡。</font></dd>
+ <dt><code>cookieStoreId</code><font>[optional_inline]</font></dt>
+ <dd><code>string</code><font>.使用此仅返回其 Cookie 存储 ID 为 的选项卡。此选项仅在加载项具有权限时<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">才可用</a>。</font><code>cookieStoreId</code><code>"cookies"</code></dd>
+ <dt><code>currentWindow</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.选项卡是否在当前窗口中。</font></dd>
+ <dt><code>discarded</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.是否丢弃选项卡。丢弃的选项卡是其内容已从内存中卸载,但仍在选项卡条中可见的选项卡。下次激活时,其内容将重新加载。</font></dd>
+ <dt><code>hidden</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.选项卡是否隐藏。</font></dd>
+ <dt><code>highlighted</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.选项卡是否突出显示。</font></dd>
+ <dt><code>index</code><font>[optional_inline]</font></dt>
+ <dd><code>integer</code><font>.选项卡在其窗口中的位置。</font></dd>
+ <dt><code>muted</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.选项卡是否为静音。</font></dd>
+ <dt><code>lastFocusedWindow</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.选项卡是否在上一个焦点窗口中。</font></dd>
+ <dt><code>pinned</code><font>[optional_inline]</font></dt>
+ <dd><code>boolean</code><font>.选项卡是否固定。</font></dd>
+ <dt><code>status</code><font>[optional_inline]</font></dt>
+ <dd>{WebExtAPIRef('选项卡。TabStatus ')=。选项卡是否已完成加载。</dd>
+ <dt><code>title</code><font>[optional_inline]</font></dt>
+ <dd><code>string</code><font>.将页面标题与图案匹配。</font></dd>
+ <dt><code>url</code><font>[optional_inline]</font></dt>
+ <dd><code><code>string</code></code><font>或。将选项卡与一个或多个匹配<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns">模式匹配</a>。请注意,片段标识符不匹配。</font><code><code>array</code> of <code><code>string</code></code></code></dd>
+ <dt><code>windowId</code><font>{{optional_inline}}</font></dt>
+ <dd><code>integer</code><font>. The of the parent window, or {{WebExtAPIRef('windows.WINDOW_ID_CURRENT')}} for the current window.</font><code>id</code></dd>
+ <dt><code>windowType</code><font>{{optional_inline}}</font></dt>
+ <dd>{{WebExtAPIRef('tabs.WindowType')}}. The type of window the tabs are in.</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h3 id="Return_value">Return value</h3>
+
+<p><font>A that will be fulfilled with an of objects, containing information about each matching tab.</font><code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code><code>array</code><code>{{WebExtAPIRef('tabs.Tab')}}</code></p>
+
+<p>If any error occurs, the promise will be rejected with an error message.</p>
+
+<h2 id="Examples">Examples</h2>
+
+<p>Get all tabs:</p>
+
+<pre class="brush: js notranslate">function logTabs(tabs) {
+ for (let tab of tabs) {
+ // tab.url requires the `tabs` permission
+ console.log(tab.url);
+ }
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+let querying = browser.tabs.query({});
+querying.then(logTabs, onError);</pre>
+
+<p>Get all tabs in the current window:</p>
+
+<pre class="brush: js notranslate">function logTabs(tabs) {
+ for (let tab of tabs) {
+ // tab.url requires the `tabs` permission
+ console.log(tab.url);
+ }
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+let querying = browser.tabs.query({currentWindow: true});
+querying.then(logTabs, onError);</pre>
+
+<p>Get the active tab in the current window:</p>
+
+<pre class="brush: js notranslate">function logTabs(tabs) {
+ // tabs[0].url requires the `tabs` permission
+ console.log(tabs[0].url);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+let querying = browser.tabs.query({currentWindow: true, active: true});
+querying.then(logTabs, onError);</pre>
+
+<p><font>Get tabs for all HTTP and HTTPS URLs under or any of its subdomains:</font><code>"mozilla.org"</code></p>
+
+<pre class="brush: js notranslate">function logTabs(tabs) {
+ for (let tab of tabs) {
+ // tab.url requires the `tabs` permission
+ console.log(tab.url);
+ }
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+let querying = browser.tabs.query({url: "*://*.mozilla.org/*"});
+querying.then(logTabs, onError);</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+
+
+<p>{{Compat("webextensions.api.tabs.query")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/tabs#method-query"><code>chrome.tabs</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/tabs.json"><code>tabs.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate">// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/index.html
new file mode 100644
index 0000000000..46641d4f60
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/index.html
@@ -0,0 +1,85 @@
+---
+title: BrowserSetting
+slug: Mozilla/Add-ons/WebExtensions/API/types/BrowserSetting
+tags:
+ - API
+ - Add-ons
+ - BrowserSetting
+ - Extensions
+ - NeedsTranslation
+ - Reference
+ - TopicStub
+ - Type
+ - Types
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/API/types/BrowserSetting
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>A <code>BrowserSetting</code> is an object representing a browser setting.</p>
+
+<p>It provides methods to set and get the setting's underlying value, to clear any change you've made to it, and to listen for changes to its value.</p>
+
+<p>Note that while this object is based on the <a href="https://developer.chrome.com/extensions/types#type-ChromeSetting">ChromeSetting</a> type, this object does not distinguish between setting the value in normal browsing windows and in private browsing windows. This means that all parts of the API relating to private browsing (such as the <code>scope</code> option to <code>ChromeSetting.set()</code>) are not implemented.</p>
+
+<h2 id="Methods">Methods</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("types.BrowserSetting.get()")}}</dt>
+ <dd>Get the current value of the setting, and an enumeration representing how the setting is currently controlled.</dd>
+ <dt>{{WebExtAPIRef("types.BrowserSetting.set()")}}</dt>
+ <dd>Set the setting to a new value.</dd>
+ <dt>{{WebExtAPIRef("types.BrowserSetting.clear()")}}</dt>
+ <dd>Clear any change made to the setting by this extension.</dd>
+</dl>
+
+<h2 id="Events">Events</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("types.BrowserSetting.onChange")}}</dt>
+ <dd>Fired when the setting's value changes.</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+
+
+<p>{{Compat("webextensions.api.types.BrowserSetting")}}</p>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/types"><code>chrome.types</code></a> API.</p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate">// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/set/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/set/index.html
new file mode 100644
index 0000000000..fc85b194bb
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/types/browsersetting/set/index.html
@@ -0,0 +1,118 @@
+---
+title: set()
+slug: Mozilla/Add-ons/WebExtensions/API/types/BrowserSetting/set
+translation_of: Mozilla/Add-ons/WebExtensions/API/types/BrowserSetting/set
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>Use <code>BrowserSetting.set()</code> to change the browser setting to a new value.</p>
+
+<p>There are some rules that can restrict when extensions are able to change settings:</p>
+
+<ul>
+ <li>some settings are locked, so they can't be changed by extensions at all</li>
+ <li>if multiple extensions try to modify the same setting, then extensions are given a precedence ordering based on when they were installed. More-recently installed extensions have precedence over less-recently installed extension.</li>
+</ul>
+
+<p>This means that if extension X tries to change a setting:</p>
+
+<ol>
+ <li>If the setting is locked, then the setting is not changed. However, X's change is remembered, and it is stored in a queue, ordered by X's precedence relative to any other extensions that tried to change the setting. If the setting becomes unlocked later on, the first extension in the queue gets to change the setting.</li>
+ <li>Otherwise, if no other extension has already changed the setting, then X succeeds in changing the setting, and is then said to "control" the setting.</li>
+ <li>Otherwise, if a lower-precedence extension Y has already changed the setting, then X succeeds in changing the setting, and now controls the setting. However, Y's change is remembered, and is stored in a queue in precedence order. If X subsequently clears its value, or if X is disabled or uninstalled,  the first extension in the queue gets to make its change to the setting.</li>
+ <li>Otherwise, if a higher-precedence extension Z has already changed the setting, then X does not succeed in changing the setting, but its change is queued. If Z subsequently clears its value, or if Z is disabled or uninstalled, the first extension in the queue gets to make its change to the setting.</li>
+</ol>
+
+<p>An extension can find out which of these scenarios applies by examining the "<code>levelOfControl</code>" property returned from a call to <code><a href="/en-US/Add-ons/WebExtensions/API/privacy/BrowserSetting/get">BrowserSetting.get()</a></code>.</p>
+
+<p>The <code><a href="/en-US/Add-ons/WebExtensions/API/privacy/BrowserSetting/set">BrowserSetting.set()</a></code> method returns a Promise that resolves to a boolean: if an attempt to change a setting actually results in the setting being changed (scenarios 2 and 3 above) the boolean is <code>true</code>: otherwise it is <code>false</code>.</p>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js notranslate">var setting = setting.set(
+ details // object
+)
+</pre>
+
+<h3 id="Parameters">Parameters</h3>
+
+<dl>
+ <dt><code>details</code></dt>
+ <dd>An object that must contain the following property:</dd>
+ <dd>
+ <dl class="reference-values">
+ <dt><code>value</code></dt>
+ <dd><code>any</code>. The value you want to change the setting to. Its type depends on the particular setting.</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h3 id="Return_value">Return value</h3>
+
+<p>A <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> that will be fulfilled with a <code>boolean</code>: <code>true</code> if the setting was modified, <code>false</code> otherwise (for example, because the extension did not control the setting).</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>See {{WebExtAPIRef("types.BrowserSetting")}}.</p>
+
+<h2 id="Example">Example</h2>
+
+<p>Modify the <code>hyperlinkAuditingEnabled</code> setting (this requires the "privacy" permission):</p>
+
+<pre class="brush: js notranslate">function onSet(result) {
+ if (result) {
+ console.log("Value was updated");
+ } else {
+ console.log("Value was not updated");
+ }
+}
+
+browser.browserAction.onClicked.addListener(() =&gt; {
+
+ var setting = browser.privacy.websites.hyperlinkAuditingEnabled.set({
+ value: false
+ });
+ setting.then(onSet);
+
+});
+</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/types"><code>chrome.types</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate">// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/types/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/types/index.html
new file mode 100644
index 0000000000..2e35b1d6e0
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/types/index.html
@@ -0,0 +1,66 @@
+---
+title: types
+slug: Mozilla/Add-ons/WebExtensions/API/types
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - NeedsTranslation
+ - Reference
+ - TopicStub
+ - Types
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/API/types
+---
+<div>{{AddonSidebar}}</div>
+
+<p>Defines the <code>BrowserSetting</code> type, which is used to represent a browser setting.</p>
+
+<h2 id="Types">Types</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("types.BrowserSetting")}}</dt>
+ <dd>Represents a browser setting.</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/types"><code>chrome.types</code></a> API.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate">// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/index.html
new file mode 100644
index 0000000000..6bb5b935e5
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/index.html
@@ -0,0 +1,155 @@
+---
+title: webNavigation
+slug: Mozilla/Add-ons/WebExtensions/API/webNavigation
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - Interface
+ - NeedsTranslation
+ - Non-standard
+ - Reference
+ - TopicStub
+ - WebExtensions
+ - webNavigation
+translation_of: Mozilla/Add-ons/WebExtensions/API/webNavigation
+---
+<div>{{AddonSidebar}}</div>
+
+<p>Add event listeners for the various stages of a navigation. A navigation consists of a frame in the browser transitioning from one URL to another, usually (but not always) in response to a user action like clicking a link or entering a URL in the location bar.</p>
+
+<p>Compared with the {{WebExtAPIRef("webRequest")}} API: navigations usually result in the browser making web requests, but the webRequest API is concerned with the lower-level view from the HTTP layer, while the webNavigation API is more concerned with the view from the browser UI itself.</p>
+
+<p>Each event corresponds to a particular stage in the navigation. The sequence of events is like this:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/13374/we-flow.png" style="display: block; height: 562px; margin-left: auto; margin-right: auto; width: 745px;"></p>
+
+<ul>
+ <li>The primary flow is:
+ <ul>
+ <li><code>{{WebExtAPIRef("webNavigation.onBeforeNavigate", "onBeforeNavigate")}}</code></li>
+ <li><code>{{WebExtAPIRef("webNavigation.onCommitted", "onCommitted")}}</code></li>
+ <li><code>{{WebExtAPIRef("webNavigation.onDOMContentLoaded", "onDOMContentLoaded")}}</code></li>
+ <li><code>{{WebExtAPIRef("webNavigation.onCompleted", "onCompleted")}}</code>.</li>
+ </ul>
+ </li>
+ <li>Additionally:
+ <ul>
+ <li><code>{{WebExtAPIRef("webNavigation.onCreatedNavigationTarget", "onCreatedNavigationTarget")}}</code> is fired before <code>onBeforeNavigate</code> if the browser needed to create a new tab or window for the navigation (for example, because the user opened a link in a new tab).</li>
+ <li>{{WebExtAPIRef("webNavigation.onHistoryStateUpdated", "onHistoryStateUpdated")}} is fired if a page uses the <a href="http://diveintohtml5.info/history.html">history API</a> to update the URL displayed in the browser's location bar.</li>
+ <li>{{WebExtAPIRef("webNavigation.onReferenceFragmentUpdated", "onReferenceFragmentUpdated")}} is fired if the <a href="https://en.wikipedia.org/wiki/Fragment_identifier">fragment identifier</a> for a page is changed.</li>
+ <li>{{WebExtAPIRef("webNavigation.onErrorOccurred", "onErrorOccurred")}} can be fired at any point.</li>
+ </ul>
+ </li>
+</ul>
+
+<p>Each navigation is a URL transition in a particular browser frame. The browser frame is identified by a tab ID and a frame ID. The frame may be the top-level browsing context in the tab, or may be a nested browsing context implemented as an <a href="/en-US/docs/Web/HTML/Element/iframe">iframe</a>.</p>
+
+<p>Each event's <code>addListener()</code> call accepts an optional filter parameter. The filter will specify one or more URL patterns, and the event will then only be fired for navigations in which the target URL matches one of the patterns.</p>
+
+<p>The <code>onCommitted</code> event listener is passed two additional properties: a {{WebExtAPIRef("webNavigation.TransitionType","TransitionType")}} indicating the cause of the navigation (for example, because the user clicked a link, or because the user selected a bookmark), and a {{WebExtAPIRef("webNavigation.TransitionQualifier","TransitionQualifier")}} providing further information about the navigation.</p>
+
+<p>To use this API you need to have the "webNavigation" <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>.</p>
+
+<h2 id="Types">Types</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("webNavigation.TransitionType")}}</dt>
+ <dd>Cause of the navigation: for example, the user clicked a link, or typed an address, or clicked a bookmark.</dd>
+ <dt>{{WebExtAPIRef("webNavigation.TransitionQualifier")}}</dt>
+ <dd>
+ <div>Extra information about a transition.</div>
+ </dd>
+</dl>
+
+<h2 id="Functions">Functions</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("webNavigation.getFrame()")}}</dt>
+ <dd>Retrieves information about a particular frame. A frame may be the top-level frame in a tab or a nested <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe">iframe</a>, and is uniquely identified by a tab ID and a frame ID.</dd>
+ <dt>{{WebExtAPIRef("webNavigation.getAllFrames()")}}</dt>
+ <dd>
+ <p>Given a tab ID, retrieves information about all the frames it contains.</p>
+ </dd>
+</dl>
+
+<h2 id="Events">Events</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("webNavigation.onBeforeNavigate")}}</dt>
+ <dd>
+ <p>Fired when the browser is about to start a navigation event.</p>
+ </dd>
+ <dt>{{WebExtAPIRef("webNavigation.onCommitted")}}</dt>
+ <dd>Fired when a navigation is committed. At least part of the new document has been received from the server and the browser has decided to switch to the new document.</dd>
+ <dt>{{WebExtAPIRef("webNavigation.onDOMContentLoaded")}}</dt>
+ <dd>Fired when the <a href="https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded">DOMContentLoaded</a> event is fired in the page.</dd>
+ <dt>{{WebExtAPIRef("webNavigation.onCompleted")}}</dt>
+ <dd>Fired when a document, including the resources it refers to, is completely loaded and initialized. This is equivalent to the DOM <code><a href="https://developer.mozilla.org/en-US/docs/Web/Events/load">load</a></code> event.</dd>
+ <dt>{{WebExtAPIRef("webNavigation.onErrorOccurred")}}</dt>
+ <dd>Fired when an error occurs and the navigation is aborted. This can happen if either a network error occurred, or the user aborted the navigation.</dd>
+ <dt>{{WebExtAPIRef("webNavigation.onCreatedNavigationTarget")}}</dt>
+ <dd>Fired when a new window, or a new tab in an existing window, is created to host a navigation: for example, if the user opens a link in a new tab.</dd>
+ <dt>{{WebExtAPIRef("webNavigation.onReferenceFragmentUpdated")}}</dt>
+ <dd>Fired if the <a class="external-icon external" href="https://en.wikipedia.org/wiki/Fragment_identifier">fragment identifier</a> for a page is changed.</dd>
+ <dt>{{WebExtAPIRef("webNavigation.onTabReplaced")}}</dt>
+ <dd>
+ <p>Fired when the contents of the tab is replaced by a different (usually previously pre-rendered) tab.</p>
+ </dd>
+ <dt>{{WebExtAPIRef("webNavigation.onHistoryStateUpdated")}}</dt>
+ <dd>Fired when the page used the <a class="external external-icon" href="http://diveintohtml5.info/history.html">history API</a> to update the URL displayed in the browser's location bar.</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.webNavigation")}}</p>
+
+<div class="hidden note">
+<p>The "Chrome incompatibilities" section is included from <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> using the <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p>
+
+<p>If you need to update this content, edit <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, then shift-refresh this page to see your changes.</p>
+</div>
+
+<h3 id="Edge_incompatibilities">Edge incompatibilities</h3>
+
+<p>Promises are not supported in Edge. Use callbacks instead.</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/webNavigation"><code>chrome.webNavigation</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/web_navigation.json"><code>web_navigation.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/ondomcontentloaded/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/ondomcontentloaded/index.html
new file mode 100644
index 0000000000..41a103dc8c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/webnavigation/ondomcontentloaded/index.html
@@ -0,0 +1,137 @@
+---
+title: webNavigation.onDOMContentLoaded
+slug: Mozilla/Add-ons/WebExtensions/API/webNavigation/onDOMContentLoaded
+tags:
+ - API
+ - onDOMContentLoaded
+ - webNavigation
+ - webNavigation.onDOMContentLoaded
+translation_of: Mozilla/Add-ons/WebExtensions/API/webNavigation/onDOMContentLoaded
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>在页面中触发<a href="/en-US/docs/Web/Events/DOMContentLoaded">DOMContentLoaded</a> 事件时触发。此时,文档被加载和解析,并且DOM被完全构造,但链接的资源(例如图像,样式表和子框架(subframes))可能尚未被加载。</p>
+
+<h2 id="Syntax">Syntax</h2>
+
+<pre class="syntaxbox brush:js">browser.webNavigation.onDOMContentLoaded.addListener(
+ listener, // function
+ filter // optional object
+)
+browser.webNavigation.onDOMContentLoaded.removeListener(listener)
+browser.webNavigation.onDOMContentLoaded.hasListener(listener)
+</pre>
+
+<p>事件有三个方法:</p>
+
+<dl>
+ <dt><code>addListener(callback)</code></dt>
+ <dd>为此事件添加监听方法.</dd>
+ <dt><code>removeListener(listener)</code></dt>
+ <dd>停止监听此事件. <code>listener</code> 参数为需要移出的监听方法.</dd>
+ <dt><code>hasListener(listener)</code></dt>
+ <dd>检测是否有 <code>listener</code> 被注册在事件上. 如果有返回 <code>true</code> , 否则返回<code>false</code> .</dd>
+</dl>
+
+<h2 id="addListener_syntax">addListener syntax</h2>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>callback</code></dt>
+ <dd>
+ <p>为当此事件发生是需要被调用的函数. 该函数将传递以下参数:</p>
+
+ <dl class="reference-values">
+ <dt><code>details</code></dt>
+ <dd><a href="#details"><code>object</code></a>. 有关导航(navigation)事件的详细信息.</dd>
+ </dl>
+ </dd>
+ <dt><code>filter</code>{{optional_inline}}</dt>
+ <dd>
+ <p><code>object</code>. 包含单个属性 <code>url</code> 的对象,  这是一个  {{WebExtAPIRef("events.UrlFilter")}} <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">数组</span></font>对象. 如果包含此参数,则该事件将仅触发转换为与数组中至少一个<code>UrlFilter</code>匹配的URL。 在数组中。如果您省略此参数,则该事件将触发所有转换。</p>
+ </dd>
+</dl>
+
+<h2 id="Additional_objects">Additional objects</h2>
+
+<h3 id="details">details</h3>
+
+<dl class="reference-values">
+ <dt><code>tabId</code></dt>
+ <dd><code>integer</code>. The ID of the tab in which the navigation has occurred.</dd>
+ <dt><code>url</code></dt>
+ <dd><code>string</code>. The URL to which the given frame has navigated.</dd>
+ <dt><code>processId</code></dt>
+ <dd><code>integer</code>. The ID of the process in which this tab is being rendered.</dd>
+ <dt><code>frameId</code></dt>
+ <dd><code>integer</code>. Frame in which the navigation is occurring. 0 indicates that navigation happens in the tab's top-level browsing context, not in a nested <a href="/en-US/docs/Web/HTML/Element/iframe">iframe</a>. A positive value indicates that navigation happens in a nested iframe. Frame IDs are unique for a given tab and process.</dd>
+ <dt><code>timeStamp</code></dt>
+ <dd><code>number</code>. The time at which <code>DOMContentLoaded</code> was fired, in <a href="https://en.wikipedia.org/wiki/Unix_time">milliseconds since the epoch</a>.</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.webNavigation.onDOMContentLoaded")}}</p>
+
+<h2 id="Examples">Examples</h2>
+
+<p>Logs the target URLs for <code>onDOMContentLoaded</code>, if the target URL's hostname contains "example.com" or starts with "developer".</p>
+
+<pre class="brush: js">var filter = {
+ url:
+ [
+ {hostContains: "example.com"},
+ {hostPrefix: "developer"}
+ ]
+}
+
+function logOnDOMContentLoaded(details) {
+ console.log("onDOMContentLoaded: " + details.url);
+}
+
+browser.webNavigation.<code>onDOMContentLoaded</code>.addListener(logOnDOMContentLoaded, filter);
+
+</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/webNavigation#event-onBeforeNavigate"><code>chrome.webNavigation</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/web_navigation.json"><code>web_navigation.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/index.html
new file mode 100644
index 0000000000..03b5823878
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/index.html
@@ -0,0 +1,186 @@
+---
+title: webRequest
+slug: Mozilla/Add-ons/WebExtensions/API/webRequest
+tags:
+ - API
+ - Add-ons
+ - Extensions
+ - Interface
+ - NeedsTranslation
+ - Non-standard
+ - Reference
+ - TopicStub
+ - WebExtensions
+ - webRequest
+translation_of: Mozilla/Add-ons/WebExtensions/API/webRequest
+---
+<div>{{AddonSidebar}}</div>
+
+<div>为发出的HTTP请求在不同阶段添加事件监听器。事件监听器可以接收到请求的详细信息,也可以修改或取消请求。</div>
+
+<h2 id="概况">概况</h2>
+
+<p>每个事件都会在请求的特定阶段触发。事件的顺序大概是这样的:</p>
+
+<p>在请求过程中的任意时间,{{WebExtAPIRef("webRequest.onErrorOccurred", "onErrorOccurred")}} 可以被触发。虽然有时候触发的事件顺序不同,举个例子,在火狐浏览器中的HSTS过程,在onBeforeRequest事件执行后,onBeforeRedirect 事件会被立即触发。</p>
+
+<p>所有的事件,接受<code>onErrorOccurred事件</code>, <code>addListener()</code>有三个参数 :</p>
+
+<ul>
+ <li>监听本身</li>
+ <li>一个{{WebExtAPIRef("webRequest.RequestFilter", "filter")}} 对象, 所以你仅可以被特定请求或特定的资源类型提醒</li>
+ <li>一个可选的<code>extraInfoSpec</code>对象. 你可以使用这个对象添加特定的事件命令</li>
+</ul>
+
+<p>这个监听函数接收一个<code>details</code>对象,这个对象包含这个请求的信息。他包含一个请求ID, 在插件中这个ID可以关联唯一个请求事件. 这个ID是浏览器会话和插件上下文中唯一的。他始终在同一个请求中,贯穿着转发和授权等事件中。</p>
+
+<p>在一个给定的主机上使用webRequest API, 你必须有这个主机的相关权限,包括"webRequest" <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">API permission</a> 和 <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">host permission</a>. 为了使用 "blocking" 特性,你必须有 "webRequestBlocking" API 权限。</p>
+
+<p>这个webRequest API不能让你进入一些安全敏感的请求,比如<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1279371">update checks and OCSP checks</a>.</p>
+
+<h3 id="Modifying_requests">Modifying requests</h3>
+
+<p>在下边这些事件中,你可以修改请求. 比如一些特别的操作:</p>
+
+<ul>
+ <li>取消请求:
+ <ul>
+ <li>{{WebExtAPIRef("webRequest.onBeforeRequest", "onBeforeRequest")}}</li>
+ <li>{{WebExtAPIRef("webRequest.onBeforeSendHeaders", "onBeforeSendHeaders")}}</li>
+ <li>{{WebExtAPIRef("webRequest.onAuthRequired", "onAuthRequired")}}</li>
+ </ul>
+ </li>
+ <li>重定向请求:
+ <ul>
+ <li>{{WebExtAPIRef("webRequest.onBeforeRequest", "onBeforeRequest")}}</li>
+ <li>{{WebExtAPIRef("webRequest.onHeadersReceived", "onHeadersReceived")}}</li>
+ </ul>
+ </li>
+ <li>修改请求头:
+ <ul>
+ <li>{{WebExtAPIRef("webRequest.onBeforeSendHeaders", "onBeforeSendHeaders")}}</li>
+ </ul>
+ </li>
+ <li>修改响应头:
+ <ul>
+ <li>{{WebExtAPIRef("webRequest.onHeadersReceived", "onHeadersReceived")}}</li>
+ </ul>
+ </li>
+ <li>加入认证功能:
+ <ul>
+ <li>{{WebExtAPIRef("webRequest.onAuthRequired", "onAuthRequired")}}</li>
+ </ul>
+ </li>
+</ul>
+
+<p>为了完成这些操作,你需要在<code>extraInfoSpec</code>参数中添加"blocking"的值到事件的<code>addListener()</code>。这将使得监听器变成同步执行。在监听器中,你可以返回一个表明需要作修改的{{WebExtAPIRef("webRequest.BlockingResponse", "BlockingResponse")}}对象:比如说,你想要发送的修改后的请求头。</p>
+
+<p>从Firefox 52开始,监听器会返回一个<code>resolve(BlockingResponse)</code> 的 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>,而不是直接返回一个<code>BlockingResponse</code>。这使得监听器可以异步地处理请求。</p>
+
+<h2 id="Types">Types</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("webRequest.ResourceType")}}</dt>
+ <dd>Represents a particular kind of resource fetched in a web request.</dd>
+ <dt>{{WebExtAPIRef("webRequest.RequestFilter")}}</dt>
+ <dd>An object describing filters to apply to webRequest events.</dd>
+ <dt>{{WebExtAPIRef("webRequest.HttpHeaders")}}</dt>
+ <dd>An array of HTTP headers. Each header is represented as an object with two properties: <code>name</code> and either <code>value</code> or <code>binaryValue</code>.</dd>
+ <dt>{{WebExtAPIRef("webRequest.BlockingResponse")}}</dt>
+ <dd>
+ <p>An object of this type is returned by event listeners that have set <code>"blocking"</code> in their <code>extraInfoSpec</code> argument. By setting particular properties in <code>BlockingResponse</code>, the listener can modify network requests.</p>
+ </dd>
+ <dt>{{WebExtAPIRef("webRequest.UploadData")}}</dt>
+ <dd>Contains data uploaded in a URL request.</dd>
+</dl>
+
+<h2 id="Properties">Properties</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("webRequest.MAX_HANDLER_BEHAVIOR_CHANGED_CALLS_PER_10_MINUTES")}}</dt>
+ <dd>The maximum number of times that <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/WebRequest/handlerBehaviorChanged" title="Suppose an add-on's job is to block web requests against a pattern, and the following scenario happens:"><code>handlerBehaviorChanged()</code></a></code> can be called in a 10 minute period.</dd>
+</dl>
+
+<h2 id="Functions">Functions</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("webRequest.handlerBehaviorChanged()")}}</dt>
+ <dd>This function can be used to ensure that event listeners are applied correctly when pages are in the browser's in-memory cache.</dd>
+</dl>
+
+<h2 id="Events">Events</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("webRequest.onBeforeRequest")}}</dt>
+ <dd>Fired when a request is about to be made, and before headers are available. This is a good place to listen if you want to cancel or redirect the request.</dd>
+ <dt>{{WebExtAPIRef("webRequest.onBeforeSendHeaders")}}</dt>
+ <dd>Fired before sending any HTTP data, but after HTTP headers are available. This is a good place to listen if you want to modify HTTP request headers.</dd>
+ <dt>{{WebExtAPIRef("webRequest.onSendHeaders")}}</dt>
+ <dd>Fired just before sending headers. If your add-on or some other add-on modified headers in <code>{{WebExtAPIRef("webRequest.onBeforeSendHeaders", "onBeforeSendHeaders")}}</code>, you'll see the modified version here.</dd>
+ <dt>{{WebExtAPIRef("webRequest.onHeadersReceived")}}</dt>
+ <dd>Fired when the HTTP response headers associated with a request have been received. You can use this event to modify HTTP response headers.</dd>
+ <dt>{{WebExtAPIRef("webRequest.onAuthRequired")}}</dt>
+ <dd>Fired when the server asks the client to provide authentication credentials. The listener can do nothing, cancel the request, or supply authentication credentials.</dd>
+ <dt>{{WebExtAPIRef("webRequest.onResponseStarted")}}</dt>
+ <dd>Fired when the first byte of the response body is received. For HTTP requests, this means that the status line and response headers are available.</dd>
+ <dt>{{WebExtAPIRef("webRequest.onBeforeRedirect")}}</dt>
+ <dd>Fired when a server-initiated redirect is about to occur.</dd>
+ <dt>{{WebExtAPIRef("webRequest.onCompleted")}}</dt>
+ <dd>Fired when a request is completed.</dd>
+ <dt>{{WebExtAPIRef("webRequest.onErrorOccurred")}}</dt>
+ <dd>Fired when an error occurs.</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p>{{Compat("webextensions.api.webRequest")}}</p>
+
+<div class="hidden note">
+<p>The "Chrome incompatibilities" section is included from <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a> using the <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> macro.</p>
+
+<p>If you need to update this content, edit <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>, then shift-refresh this page to see your changes.</p>
+</div>
+
+<h3 id="Edge_incompatibilities">Edge incompatibilities</h3>
+
+<p>Promises are not supported in Edge. Use callbacks instead.</p>
+
+<p>{{Compat("webextensions.api.webRequest")}} {{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/webRequest"><code>chrome.webRequest</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/web_request.json"><code>web_request.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre class="notranslate">// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/requestfilter/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/requestfilter/index.html
new file mode 100644
index 0000000000..6ac538c374
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/webrequest/requestfilter/index.html
@@ -0,0 +1,71 @@
+---
+title: webRequest.RequestFilter
+slug: Mozilla/Add-ons/WebExtensions/API/webRequest/RequestFilter
+tags:
+ - webRequest
+translation_of: Mozilla/Add-ons/WebExtensions/API/webRequest/RequestFilter
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>webRequest事件参数</p>
+
+<h2 id="Type">Type</h2>
+
+<p>该参数值是一个对象,包括以下属性:</p>
+
+<dl class="reference-values">
+ <dt><code>urls</code></dt>
+ <dd><font face="Consolas, Liberation Mono, Courier, monospace">字符串数组类型,数组内的每个字符串为<a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/Match_patterns">模式匹配</a>格式。当请求地址符合给定模式时,事件监听器才会响应。需注意的是,仅支持http和HTTPS协议的参数地址,其他协议即使与该给定模式匹配也不会响应。</font></dd>
+ <dt><code>types</code>{{optional_inline}}</dt>
+ <dd>webRequest.ResourceType类型的数组,表示资源类型列表。例如:stylesheets、images、scripts。事件监听器仅响应出现在该指定列表的资源类型。</dd>
+ <dt><code>tabId</code>{{optional_inline}}</dt>
+ <dd><font face="Consolas, Liberation Mono, Courier, monospace">数值类型,与</font>{{WebExtAPIRef("tabs.Tab", "tab")}}关联,事件监听器仅响应指定了该tabId的请求。</dd>
+ <dt><code>windowId</code>{{optional_inline}}</dt>
+ <dd><font face="Consolas, Liberation Mono, Courier, monospace">数值类型,与</font>{{WebExtAPIRef("windows.Window", "window")}}关联,事件监听器仅响应指定了该<code>windowId</code>的请求。</dd>
+</dl>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.webRequest.RequestFilter")}}</p>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>告知信息</strong>
+
+<p>该API基于Chromium的 <a href="https://developer.chrome.com/extensions/webRequest#type-RequestFilter"><code>chrome.webRequest</code></a> API. 该文档来源于Chromium代码中的 <a href="https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/web_request.json"><code>web_request.json</code></a> 。</p>
+
+<p>Microsoft Edge兼容性数据由Microsoft Corporation提供,并包含在Creative Commons Attribution 3.0 United States License下。</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/windows/create/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/windows/create/index.html
new file mode 100644
index 0000000000..7673eadc83
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/windows/create/index.html
@@ -0,0 +1,169 @@
+---
+title: windows.create()
+slug: Mozilla/Add-ons/WebExtensions/API/windows/create
+translation_of: Mozilla/Add-ons/WebExtensions/API/windows/create
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>创建一个新的窗口.</p>
+
+<p>当你创建一个窗口时,你可以:</p>
+
+<ul>
+ <li>加载一个或多个新的标签到该窗口中.</li>
+ <li>将一个现有窗口的.标签移动到新的窗口中</li>
+ <li>设置窗口的大小和位置</li>
+ <li>创建一个面板样式的窗口,它没有浏览器的默认样式(地址栏,工具栏等)</li>
+ <li>设置窗口的多种属性, 像是获得焦点或是为隐私窗口.</li>
+</ul>
+
+<p>这是一个异步的方法返回一个 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>.</p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">var creating = browser.windows.create(
+ createData // optional object
+)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>createData</code>{{optional_inline}}</dt>
+ <dd><code>object</code>.</dd>
+ <dd>
+ <dl class="reference-values">
+ <dt><code>url</code>{{optional_inline}}</dt>
+ <dd><code><code>字符串或字符串数组</code></code>. 一个URL或都URL数组要在该窗口中打开成标签页的. 完整的需要包括scheme (像. <code>http://www.google.com</code>, not <code>www.google.com</code>). 相对路径将相对于该拓展中的当前页. 默认为打开新标签页.</dd>
+ <dt><code>tabId</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. 如果设置了该值,将该tab从一个现有的窗口中移到新窗口中.</dd>
+ <dt><code>left</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. 窗口左边到屏幕左边缘的距离.如果没有设定,新窗口将按上一个焦点窗口定位水平位置. 对于panel样式窗口,该值不起作用.</dd>
+ <dt><code>top</code>{{optional_inline}}</dt>
+ <dd>窗口顶部到屏幕的顶部距离.如果没有设定,新窗口将按上一个焦点窗口定位垂直位置. 对于panel样式窗口,该值不起作用.</dd>
+ <dt><code>width</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. 新窗口的宽度, 包含框架. 未设定则使用默认宽度。.</dd>
+ <dt><code>height</code>{{optional_inline}}</dt>
+ <dd><code>integer</code>. 新窗口的高度, 包含框架. 未设定则使用默认高度。.</dd>
+ <dt><code>focused</code>{{optional_inline}}</dt>
+ <dd><code>boolean</code>.如果 为<code>true</code>, 新窗口将获取焦点. 否则新窗口当在后台打开并且当前焦点窗口继续保持焦点.。.默认为true</dd>
+ <dt><code>incognito</code>{{optional_inline}}</dt>
+ <dd><code>boolean</code>. 是否打开为一个隐私窗口. <code>如果设定为隐私窗口并且引入了tabId</code>, 则tabId对应的标签必须是一个隐私标签— 即不能把一个不是隐私标签的标签页移动到隐私窗口中。</dd>
+ <dt><code>type</code>{{optional_inline}}</dt>
+ <dd>一{{WebExtAPIRef('windows.CreateType')}} 值,表示创建窗口的类型. <code>panel</code> 或者<code>popup</code> 样式将打开一个没有默认浏览器样式的窗口 (地址栏,工具栏等)。</dd>
+ <dt><code>state</code>{{optional_inline}}</dt>
+ <dd>一个 {{WebExtAPIRef('windows.WindowState')}} 值, 窗口的祲状态。 最小化、最大化、全屏状态不能与<code>left</code>, <code>top</code>, <code>width</code>, or <code>height</code>属性一起使用。</dd>
+ </dl>
+ </dd>
+</dl>
+
+<h3 id="返回值">返回值</h3>
+
+<p>一个 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> 其中传入一个包含新窗口细节的 {{WebExtAPIRef('windows.Window')}} 对象。 这个{{WebExtAPIRef('windows.Window')}} 有自己的tabs属性集 ,而不像 {{WebExtAPIRef("windows.get()")}}返回的窗口对象和相似的API,  如果传递了populate项其仅仅包含tabs. 如果发生了错误 promise will be rejected with an error message.</p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">这个页面中的兼容性表是从结构化数据生成的。如果你想为数据,请参照 <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 并且给我们发请求</p>
+
+<p>{{Compat("webextensions.api.windows.create", 10)}}</p>
+
+<h2 id="示例">示例</h2>
+
+<p>打开一个包含两个标签的窗口</p>
+
+<pre class="brush: js">function onCreated(windowInfo) {
+ console.log(`Created window: ${windowInfo.id}`);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+browser.browserAction.onClicked.addListener((tab) =&gt; {
+ var creating = browser.windows.create({
+ url: ["https://developer.mozilla.org",
+ "https://addons.mozilla.org"]
+ });
+ creating.then(onCreated, onError);
+});</pre>
+
+<p>当用户点击一个browser action打开一个窗口,并且将当前活跃的标签移动其中</p>
+
+<pre class="brush: js">function onCreated(windowInfo) {
+ console.log(`Created window: ${windowInfo.id}`);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+browser.browserAction.onClicked.addListener((tab) =&gt; {
+ var creating = browser.windows.create({
+ tabId: tab.id
+ });
+ creating.then(onCreated, onError);
+});</pre>
+
+<p>打开一个小面板样式的窗口,并且加载一个本地包中的文件到其中</p>
+
+<pre class="brush: js">function onCreated(windowInfo) {
+ console.log(`Created window: ${windowInfo.id}`);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+browser.browserAction.onClicked.addListener((tab) =&gt; {
+
+ var popupURL = browser.extension.getURL("popup/popup.html");
+
+ var creating = browser.windows.create({
+ url: popupURL,
+ type: "popup",
+ height: 200,
+ width: 200
+ });
+ creating.then(onCreated, onError);
+
+});</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/windows#method-create"><code>chrome.windows</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/windows.json"><code>windows.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/windows/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/windows/index.html
new file mode 100644
index 0000000000..b923176e30
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/windows/index.html
@@ -0,0 +1,116 @@
+---
+title: windows
+slug: Mozilla/Add-ons/WebExtensions/API/windows
+translation_of: Mozilla/Add-ons/WebExtensions/API/windows
+---
+<div>{{AddonSidebar}}</div>
+
+<p>与浏览器窗口互动。您可以使用此 API 获取有关已打开窗口的信息,以及打开、修改和关闭窗口。您也可以监听窗口的打开、关闭和其激活事件。</p>
+
+<h2 id="类型">类型</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("windows.WindowType")}}</dt>
+ <dd>浏览器窗口的类型。</dd>
+ <dt>{{WebExtAPIRef("windows.WindowState")}}</dt>
+ <dd>浏览器窗口的状态。</dd>
+ <dt>{{WebExtAPIRef("windows.Window")}}</dt>
+ <dd>有关一个浏览器窗口的信息。</dd>
+ <dt>{{WebExtAPIRef("windows.CreateType")}}</dt>
+ <dd>指定要创建的浏览器窗口的类型。</dd>
+</dl>
+
+<h2 id="属性">属性</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("windows.WINDOW_ID_NONE")}}</dt>
+ <dd><code>windowId</code> 值表示不存在浏览器窗口。</dd>
+ <dt>{{WebExtAPIRef("windows.WINDOW_ID_CURRENT")}}</dt>
+ <dd><code>windowId</code> 值表示当前窗口。</dd>
+</dl>
+
+<h2 id="函数">函数</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("windows.get()")}}</dt>
+ <dd>指定其 ID,获取一个窗口的细节。</dd>
+ <dt>{{WebExtAPIRef("windows.getCurrent()")}}</dt>
+ <dd>获取当前窗口。</dd>
+ <dt>{{WebExtAPIRef("windows.getLastFocused()")}}</dt>
+ <dd>获取最近获得焦点的窗口,通常它是“顶部”的窗口。</dd>
+ <dt>{{WebExtAPIRef("windows.getAll()")}}</dt>
+ <dd>获取所有窗口。</dd>
+ <dt>{{WebExtAPIRef("windows.create()")}}</dt>
+ <dd>
+ <p>创建新窗口。</p>
+ </dd>
+ <dt>{{WebExtAPIRef("windows.update()")}}</dt>
+ <dd>更新一个窗口的属性。使用此项对移动、调整大小、聚焦/取消聚焦等。</dd>
+ <dt>{{WebExtAPIRef("windows.remove()")}}</dt>
+ <dd>关闭一个窗口及其所有标签页。</dd>
+</dl>
+
+<h2 id="事件">事件</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("windows.onCreated")}}</dt>
+ <dd>一个窗口创建时触发。</dd>
+ <dt>{{WebExtAPIRef("windows.onRemoved")}}</dt>
+ <dd>一个窗口关闭时触发。</dd>
+ <dt>{{WebExtAPIRef("windows.onFocusChanged")}}</dt>
+ <dd>当前有焦点的窗口改变时触发。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.windows")}}</p>
+
+<div class="hidden note">
+<p>Chrome 的不兼容 部分列在 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities"> https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>,为采用 <a href="/en-US/docs/Template:WebExtChromeCompat">WebExtChromeCompat</a> 宏。</p>
+
+<p>如果您需要更新此内容,编辑 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Chrome_incompatibilities</a>,然后按住Shift并刷新此页面以查看您的变更。</p>
+</div>
+
+<h3 id="Edge_的不兼容">Edge 的不兼容</h3>
+
+<p>Edge 中不支持 Promises。需使用回调。</p>
+
+<p>{{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>声明</strong>
+
+<p>此 API 基于 Chromium 的 <a href="https://developer.chrome.com/extensions/windows"><code>chrome.windows</code></a> API。此文档基于 Chromium 代码中的<a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/windows.json"><code> windows.json</code></a>。</p>
+
+<p>Microsoft Edge 兼容性数据由微软公司提供,并包含在创作共用 署名 3.0美国许可证下。</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowstate/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowstate/index.html
new file mode 100644
index 0000000000..605f2cf071
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowstate/index.html
@@ -0,0 +1,66 @@
+---
+title: windows.WindowState
+slug: Mozilla/Add-ons/WebExtensions/API/windows/WindowState
+translation_of: Mozilla/Add-ons/WebExtensions/API/windows/WindowState
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>浏览器窗口的状态。</p>
+
+<h2 id="类型">类型</h2>
+
+<p>类型的值是字符串类型。 可能的值如下:</p>
+
+<ul>
+ <li><code>"normal"</code></li>
+ <li><code>"minimized"</code></li>
+ <li><code>"maximized"</code></li>
+ <li><code>"fullscreen"</code></li>
+ <li><code>"docked"</code></li>
+</ul>
+
+<h2 id="浏览器适配">浏览器适配</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.windows.WindowState")}}</p>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>致谢</strong>
+
+<p>此API基于谷歌浏览器 <a href="https://developer.chrome.com/extensions/windows#type-WindowState"><code>chrome.windows</code></a> API。此文档源于谷歌源码 <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/windows.json"><code>windows.json</code></a> .</p>
+
+<p>微软Edge浏览器兼容性数据由微软公司提供,并包含在美国Creative Commons Attribution 3.0许可证下。</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowtype/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowtype/index.html
new file mode 100644
index 0000000000..6f9e5572b2
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/windows/windowtype/index.html
@@ -0,0 +1,65 @@
+---
+title: windows.WindowType
+slug: Mozilla/Add-ons/WebExtensions/API/windows/WindowType
+translation_of: Mozilla/Add-ons/WebExtensions/API/windows/WindowType
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>浏览器窗口的类型。</p>
+
+<h2 id="Type">Type</h2>
+
+<p>类型的值是字符串类型。 可能的值如下:</p>
+
+<ul>
+ <li><code>"normal"</code></li>
+ <li><code>"popup"</code></li>
+ <li><code>"panel"</code></li>
+ <li><code>"devtools"</code></li>
+</ul>
+
+<h2 id="浏览器适配">浏览器适配</h2>
+
+
+
+<p>{{Compat("webextensions.api.windows.WindowType")}}</p>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>Acknowledgements</strong>
+
+<p>This API is based on Chromium's <a href="https://developer.chrome.com/extensions/windows#type-WindowType"><code>chrome.windows</code></a> API. This documentation is derived from <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/windows.json"><code>windows.json</code></a> in the Chromium code.</p>
+
+<p>Microsoft Edge compatibility data is supplied by Microsoft Corporation and is included here under the Creative Commons Attribution 3.0 United States License.</p>
+</div>
+
+<div class="hidden">
+<pre>// Copyright 2015 The Chromium Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+</pre>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/剪切板/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/剪切板/index.html
new file mode 100644
index 0000000000..5fecb4334f
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/剪切板/index.html
@@ -0,0 +1,36 @@
+---
+title: clipboard
+slug: Mozilla/Add-ons/WebExtensions/API/剪切板
+tags:
+ - 剪切板
+ - 扩展
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/API/clipboard
+---
+<div>{{AddonSidebar}}</div>
+
+<p>WebExtention 的 <code>clipboard</code> API 增加了一个将图像复制到剪贴板的函数。目前,这个 API 仅支持复制图像,但我们期望它未来支持复制文本和 HTML(译者注:原文如此,可能是指被支持复制富内容之后的标准剪贴板 API 取代)。</p>
+
+<p>这个  WebExtension API 之所以存在,主要是因为标准的 Web 剪贴板 API <a href="/zh-CN/docs/Web/API/Clipboard_API">Clipboard API</a> 不支持将图像写入剪贴板。一旦标准剪贴板 API 对非文本剪贴板内容的支持进入通用状态,则此 API 可能会被弃用。</p>
+
+<p>Reading from the clipboard is not supported by this API, because the clipboard can already be read using the standard web platform APIs. See <a href="https://wiki.developer.mozilla.org/en-US/Add-ons/WebExtensions/Interact_with_the_clipboard#Reading_from_the_clipboard">Interacting with the clipboard</a>.</p>
+
+<p>This API is based on Chrome's <code><a class="external external-icon" href="https://developer.chrome.com/apps/clipboard">clipboard</a></code> API, but that API is only available for Chrome apps, not extensions.</p>
+
+<p>To use this API you need the <code>"clipboardWrite"</code> extension <a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>.</p>
+
+<h2 id="函数">函数</h2>
+
+<dl>
+ <dt>{{WebExtAPIRef("clipboard.setImageData()")}}</dt>
+ <dd>复制图像到剪切板。</dd>
+</dl>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.api.clipboard")}} {{WebExtExamples("h2")}}</p>
+
+<div class="note"><strong>说明</strong>
+
+<p> 此 API 基于 Chromium 的 <a href="https://developer.chrome.com/apps/clipboard"><code>chrome.clipboard</code></a> API.</p>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/api/剪切板/setimagedata/index.html b/files/zh-cn/mozilla/add-ons/webextensions/api/剪切板/setimagedata/index.html
new file mode 100644
index 0000000000..3cdaf45b08
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/api/剪切板/setimagedata/index.html
@@ -0,0 +1,79 @@
+---
+title: clipboard.setImageData()
+slug: Mozilla/Add-ons/WebExtensions/API/剪切板/setImageData
+tags:
+ - API
+ - Clipboard
+ - 剪贴板
+ - 参考
+ - 拓展
+ - 方法
+translation_of: Mozilla/Add-ons/WebExtensions/API/clipboard/setImageData
+---
+<div>{{AddonSidebar()}}</div>
+
+<p>将图像复制到剪贴板。在将图像写入剪贴板之前,会对图像进行重新编码。如果图像无效,则不会修改剪贴板。</p>
+
+<p>图像被作为包含经过编码的图像的 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer">ArrayBuffer</a></code> 提供。支持 JPEG 和 PNG 格式。</p>
+
+<p>基于 Chrome 的 <code><a href="https://developer.chrome.com/apps/clipboard" rel="noopener">clipboard.setImageData()</a></code> API,但存在一些差异:</p>
+
+<ul>
+ <li>Chrome API 仅适用于应用,不适用于扩展程序。</li>
+ <li>此API需要 <code>"clipboardWrite"</code> 权限,Chrome 版本需要 <code>"clipboard"</code> 权限。</li>
+ <li>Chrome 的 API 使用回调,此 API 使用 Promise。</li>
+ <li>此 API 不支持 <code>additionalItems</code> 参数。</li>
+</ul>
+
+<p>这是一个返回 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> 的异步函数。</p>
+
+<h2 id="语法">语法</h2>
+
+<pre class="syntaxbox brush:js">browser.clipboard.setImageData(<em>imageData</em>, <em>imageType</em>)
+</pre>
+
+<h3 id="参数">参数</h3>
+
+<dl>
+ <dt><code>imageData</code></dt>
+ <dd>An <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer">ArrayBuffer</a></code> containing the encoded image data to copy to the clipboard.</dd>
+ <dt><code>imageType</code></dt>
+ <dd>A {{domxref("DOMString")}} indicating the type of image contained in <code>imageData</code>: <code>"png"</code> or <code>"jpeg"</code>.</dd>
+</dl>
+
+<h3 id="返回值">返回值</h3>
+
+<p>A <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code> that will be resolved with no arguments if the operation succeeded, or rejected if there was an error (for example, because the data did not represent a valid image).</p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.api.clipboard.setImageData", 10)}}</p>
+
+<h2 id="示例">示例</h2>
+
+<p>Copy a remote image:</p>
+
+<pre class="brush: js" id="ct-71"><span class="quote">// requires:
+// * the host permission for "<a href="https://cdn.mdn.mozilla.net/" rel="nofollow">https://cdn.mdn.mozilla.net/</a>*"
+// * the API permission "clipboardWrite"
+
+fetch('<a href="https://cdn.mdn.mozilla.net/static/img/favicon144.png" rel="nofollow">https://cdn.mdn.mozilla.net/static/img/favicon144.png</a>')
+.then(response =&gt; response.arrayBuffer())
+.then(buffer =&gt; browser.clipboard.setImageData(buffer, 'png'));</span></pre>
+
+<p><span class="quote">Copy an image that was bundled with the extension:</span></p>
+
+<pre class="brush: js" id="ct-70">// requires <span class="quote">the API permission </span>"clipboardWrite"
+
+fetch(browser.runtime.getURL('image.png'))
+.then(response =&gt; response.arrayBuffer())
+.then(buffer =&gt; browser.clipboard.setImageData(buffer, 'png'));</pre>
+
+<p>{{WebExtExamples}}</p>
+
+<div class="note"><strong>说明</strong>
+
+<p> 此 API 基于 Chromium 的 <a href="https://developer.chrome.com/apps/clipboard"><code>chrome.clipboard</code></a> API.</p>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/browser_support_for_javascript_apis/index.html b/files/zh-cn/mozilla/add-ons/webextensions/browser_support_for_javascript_apis/index.html
new file mode 100644
index 0000000000..f2ba32173b
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/browser_support_for_javascript_apis/index.html
@@ -0,0 +1,17 @@
+---
+title: Browser support for JavaScript APIs
+slug: Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs
+tags:
+ - WebExtension
+translation_of: Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs
+---
+<div>{{AddonSidebar}}</div>
+
+<div>{{WebExtAllCompatTables}}</div>
+
+<p class="hidden">此页面的兼容性表格由结构化的数据生成。如果你想为这份数据出一些力,请看看 <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 并发给我们一个 pull request。</p>
+
+<div class="note"><strong>致谢</strong>
+
+<p>Microsoft Edge 的兼容性数据由 Microsoft 公司提供,依照知识共享署名 3.0 美国协议授权。</p>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/chrome_incompatibilities/index.html b/files/zh-cn/mozilla/add-ons/webextensions/chrome_incompatibilities/index.html
new file mode 100644
index 0000000000..8cc71470f9
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/chrome_incompatibilities/index.html
@@ -0,0 +1,154 @@
+---
+title: Chrome 不兼容情况
+slug: Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities
+tags:
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities
+---
+<div>{{AddonSidebar}}</div>
+
+<p>使用WebExtension API构建的扩展旨在与Chrome和Opera扩展兼容:尽可能为这些浏览器编写的扩展应该在Firefox上运行,并且只需进行极少的更改。</p>
+
+<p>但是,Firefox目前仅支持Chrome和Opera支持的有限功能和API。 我们正在努力增加更多的支持,但许多功能尚未得到支持,我们可能永远不会支持某些功能。</p>
+
+<h2 id="JavaScript_APIs">JavaScript APIs</h2>
+
+<h3 id="回调与_chrome.*_命名空间">回调与 chrome.* 命名空间</h3>
+
+<p>在 Chrome 中,扩展通过使用 <code>chrome</code> 命名空间来访问私有 JavaScript API:</p>
+
+<pre class="brush: js line-numbers language-js">chrome.browserAction.setIcon({path: "path/to/icon.png"});</pre>
+
+<p>WebExtensions 通过使用 <code>browser</code> 命名空间来访问等价的 API:</p>
+
+<pre class="brush: js line-numbers language-js">browser.browserAction.setIcon({path: "path/to/icon.png"});</pre>
+
+<p>许多 API 是异步的。在 Chrome 中,异步的 API 使用回调来返回值,使用 {{WebExtAPIRef("runtime.lastError")}} 来与传达错误:</p>
+
+<pre class="brush: js line-numbers language-js">function logCookie(c) {
+ if (chrome.extension.lastError) {
+ console.error(chrome.extension.lastError);
+ } else {
+ console.log(c);
+ }
+}
+
+chrome.cookies.set(
+ {url: "https://developer.mozilla.org/"},
+ logCookie
+);</pre>
+
+<p>在 WebExtensions 中应使用 <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promises</a> 来访问等价的 API:</p>
+
+<pre class="brush: js ">function logCookie(c) {
+ console.log(c);
+}
+
+function logError(e) {
+ console.error(e);
+}
+
+var setCookie = browser.cookies.set(
+ {url: "https://developer.mozilla.org/"}
+);
+setCookie.then(logCookie, logError);
+</pre>
+
+<h3 id="Firefox_支持_chrome_和_browser_命名空间">Firefox 支持 <code>chrome</code> 和 <code>browser</code> 命名空间</h3>
+
+<p>为了帮助移植,Firefox 的 WebExtension 实现支持 <code>chrome</code> 与回调和 <code>browser</code> 与 promise。这意味着许多 Chrome 扩展无须修改就能在 Firefox 上运行。然而并不是 WebExtension 标准的一部分,也许不会被所有兼容 WebExtension的浏览器支持。</p>
+
+<p>如果你在编写 WebExtension 时确实要用到 <code>browser</code> 和 promise,我们也开发了polyfill 来保证扩展可以在 Chrome 里运行:<a href="https://github.com/mozilla/webextension-polyfill">https://github.com/mozilla/webextension-polyfill</a>.</p>
+
+<h3 id="部分受支持的_API">部分受支持的 API</h3>
+
+<p>页面 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs">JavaScript API 的浏览器支持情况</a> 包含了介绍受 Firefox 任意程度支持的 API 的兼容性表格。若对 API 的支持存在须要注意的事项,并标有星号“*”,且在 API 的参考页面会介绍注意事项。</p>
+
+<p>这些表格由 <a href="https://github.com/mdn/browser-compat-data">在 GitHub 上以 JSON 文件存储的兼容性数据</a>生成。</p>
+
+<p>本节剩余部分介绍了表格未涵盖的兼容性问题。</p>
+
+<h4 id="notifications"><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/notifications">notifications</a></h4>
+
+<ul>
+ <li>For <code>notifications.create(), with the "basic"</code> <code><a href="/en-US/Add-ons/WebExtensions/API/notifications/TemplateType">type</a></code>, <code>iconUrl</code> is optional in Firefox. It is required in Chrome.</li>
+ <li>Notifications are cleared immediately when the user clicks on them. This is not the case in Chrome.</li>
+ <li>If you call <code>notifications.create()</code> more than once in rapid succession, Firefox may end up not displaying any notification at all. Waiting to make subsequent calls until within the <code>chrome.notifications.create() callback</code> function is not a sufficiently long delay to prevent this from happening.</li>
+</ul>
+
+<h4 id="proxy"><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/proxy">proxy</a></h4>
+
+<ul>
+ <li>This API is completely different to the design of the Chrome API. With Chrome's API an extension can register a PAC file, but can also define explicit proxying rules. Since this is also possible using the extended PAC files, this API only supports the PAC file approach. Because this API is incompatible with the Chrome <code>proxy</code> API, this API is only available through the <code>browser</code> namespace.</li>
+</ul>
+
+<h4 id="tabs"><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs">tabs</a></h4>
+
+<ul>
+ <li>
+ <p>In Firefox, relative URLs passed into <code>tabs.executeScript()</code> or <code>tabs.insertCSS()</code> are resolved relative to the current page URL. In Chrome, these URLs are resolved relative to the add-on's base URL. To work cross-browser, you can specify the path as an absolute URL, starting at the add-on's root, like this:</p>
+
+ <pre class="brush: html">/path/to/script.js</pre>
+ </li>
+ <li>在 Firefox 中,用 <code>tabs.query() </code>根据 URL 查询标签页需要有<code>"tabs"</code> 权限。在 Chrome 中,没有<code>"tabs"</code>权限也可以,但结果将限制在 URL 匹配主机权限的标签页。</li>
+</ul>
+
+<h4 id="webRequest"><a href="/en-US/Add-ons/WebExtensions/API/webRequest">webRequest</a></h4>
+
+<ul>
+ <li>在Firefx中,只有原网址使用 <code>http:</code> <code>或 https:</code> 协议时所请求的重定向才有效。</li>
+ <li>In Firefox, events are not fired for system requests (for example, extension upgrades or searchbar suggestions). From Firefox 57 onwards, Firefox makes an exception for extensions that need to intercept {{WebExtAPIRef("webRequest.onAuthRequired")}} for proxy authorization. See the documentation for {{WebExtAPIRef("webRequest.onAuthRequired")}}.</li>
+ <li>In Firefox, if an extension wants to redirect a public (e.g. HTTPS) URL to an <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Extension_pages">extension page</a>, the extension's manifest.json file must contain a <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/web_accessible_resources">web_accessible_resources</a> key that lists the URL for the extension page. Note that any website may then link or redirect to that url, and extensions should treat any input (POST data, for examples) as if it came from an untrusted source, just as a normal web page should.</li>
+</ul>
+
+<h4 id="windows"><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows">windows</a></h4>
+
+<ul>
+ <li>Firefox 中 <code>onFocusChanged</code> 对于指定的焦点变化将触发多次。</li>
+</ul>
+
+<h3 id="其他不兼容情况">其他不兼容情况</h3>
+
+<h4 id="CSS_中的_URL">CSS 中的 URL</h4>
+
+<p>Firefox 解析 CSS 中嵌入的 URL  时,若 URL 时相对地址,将是相对 CSS 文件,而不是被嵌入的网页文件。</p>
+
+<h4 id="更多不兼容情况">更多不兼容情况</h4>
+
+<p>Firefox 不支持从后台标签页使用 <code><a href="/en-US/docs/Web/API/Window/alert">alert()、</a><a href="/en-US/docs/Web/API/Window/confirm">confirm()</a></code> 或<code><a href="/en-US/docs/Web/API/Window/prompt"> prompt()</a></code>。</p>
+
+<h4 id="web_accessible_resources">web_accessible_resources</h4>
+
+<p>在 Chrome 中,若资源在 web_accessible_resources 中列出,即可通过 chrome-extension://&lt;your-extension-id&gt;/&lt;path/to/resource&gt; 访问。每个扩展的 ID 都是固定的。</p>
+
+<p>Firefox 以不同方式进行实现。它使用一个随机的 UUID,在每个 Firefox 实例中都不同:moz-extension://&lt;random-UUID&gt;/&lt;path/to/resource&gt;。这一随机性可能会让你无法实现某些东西,例如你无法将特定扩展的 URL 添加到另一个域名的 CSP 策略中。</p>
+
+<h4 id="Manifest_key_属性">Manifest "key" 属性</h4>
+
+<p>对于解包了的扩展,Chrome 允许将 <a href="https://developer.chrome.com/extensions/manifest/key">"key" 属性</a>添加到 manifest,以确保在不同机器上的扩展 ID 不变。这主要在使用 web_accessible_resources 时有用。鉴于 Firefox 为 web_accessible_resources 使用随机的 UUID,此属性不受支持。</p>
+
+<h4 id="Content_script_requests_happen_in_the_context_of_extension_not_content_page">Content script requests happen in the context of extension, not content page</h4>
+
+<p>In Chrome when request is called (for example, using <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch">fetch()</a></code>) to relative URL like <code>/api</code> from content script, it will be sent to <code>https://example.com/api</code>. In Firefox you have to provide absolute URLs. </p>
+
+<h2 id="manifest.json_键">manifest.json 键</h2>
+
+<p>The main <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> page includes a table describing browser support for manifest.json keys. Where there are caveats around support for a given key, this is indicated in the table with an asterisk "*" and in the reference page for the key, the caveats are explained.</p>
+
+<p>These tables are generated from compatibility data stored as <a href="https://github.com/mdn/browser-compat-data">JSON files in GitHub</a>.</p>
+
+<h2 id="Native_messaging">Native messaging</h2>
+
+<h3 id="Command-line_arguments">Command-line arguments</h3>
+
+<p>On Linux and Mac, Chrome passes one argument to the native app, which is the origin of the extension that started it, in the form: <code>chrome-extension://[extensionID]</code>. This enables the app to identify the extension.</p>
+
+<p>On Windows, Chrome passes two arguments: the first is the origin of the extension, and the second is a handle to the Chrome native window that started the app.</p>
+
+<h3 id="allowed_extensions">allowed_extensions</h3>
+
+<p>In Chrome, the <code>allowed_extensions</code> key in the app manifest is called <code>allowed_origins</code> instead.</p>
+
+<h3 id="App_manifest_location">App manifest location</h3>
+
+<p>Chrome expects to find the app manifest in a different place. See <a href="https://developer.chrome.com/extensions/nativeMessaging#native-messaging-host-location">Native messaging host location</a> in the Chrome docs. </p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/content_scripts/index.html b/files/zh-cn/mozilla/add-ons/webextensions/content_scripts/index.html
new file mode 100644
index 0000000000..4fe6a88055
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/content_scripts/index.html
@@ -0,0 +1,575 @@
+---
+title: Content scripts
+slug: Mozilla/Add-ons/WebExtensions/Content_scripts
+translation_of: Mozilla/Add-ons/WebExtensions/Content_scripts
+---
+<div>{{AddonSidebar}}</div>
+
+<p>Content script 是你扩展的一部分,运行于一个特定的网页环境(而并不是后台脚本,后台脚本是扩展的一部分,也不是该网页利用 {{HTMLElement("script")}} 加载的一个脚本,{{HTMLElement("script")}} 加载的脚本是网页的一部分)。</p>
+
+<p>后台脚本可以访问所有WebExtension JavaScript APIS,但是他们不能直接访问网页的内容,所以如果你需要Content Scripts来做到这点。</p>
+
+<p>就像通常的网页加载的脚本一样,Content Scripts 可以使用standard DOM APIS 读取和修改页面内容。</p>
+
+<p>Content Script 只能访问WebExtension APIS 的一个小的子集,但是它们可以使用通信系统与后台脚本进行通信,从而间接的访问WebExtension APIS。</p>
+
+<div class="note">
+<p>注意content scripts 在addons.mozilla.org现在已被禁止,如果你在这个域名尝试插入一个Content script将会失败而这个页面会LOG一个CSP错误。</p>
+</div>
+
+<h2 id="加载Content_scripts">加载Content scripts</h2>
+
+<p>你可以通过两种方法之一在一个页面加载Content script:</p>
+
+<ul>
+ <li><strong>声明式</strong>: 在你的manifest.json中使用content_scripts关键字,你可以要求浏览器每当加载一个与指定正则表达式匹配的网页时加载一个Content Script。</li>
+ <li><strong>程序式</strong>: 使用 <code><a href="/en-US/Add-ons/WebExtensions/API/Tabs/executeScript">tabs.executeScript()</a></code> API, 你可以在任何你想要的时候加载一个Content script 到一个指定的标签:比如,作为用户点击事件的回应。</li>
+</ul>
+
+<p>在每一个extension的每一个frame中,只有一个全局作用域。所以在一个content script中的变量可以被另外的content script访问到,而与content script如何被加载无关。</p>
+
+<h2 id="Content_script_环境">Content script 环境</h2>
+
+<h3 id="DOM_访问">DOM 访问</h3>
+
+<p>Content scripts 可以访问和修改页面的DOM,就像普通的页面脚本一样。他们也可以察觉页面脚本对页面做出的任何修改。</p>
+
+<p>不过,content scripts 得到的是一个“干净的DOM视图”,这意味着:</p>
+
+<ul>
+ <li>content scripts 不能看见页面脚本定义的javascript 变量。</li>
+ <li>如果一个页面脚本重定义了一个DOM内置属性,content scripts将获取到这个属性的原始版本,而不是重定义版本。</li>
+</ul>
+
+<p>在 Gecko(译者注:Gecko是由 Mozilla 工程开发出的布局引擎的名字), 这种行为被称为射线视觉。</p>
+
+<p>举个例子,考虑一个网页如下:</p>
+
+<pre class="brush: html">&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;meta http-equiv="content-type" content="text/html; charset=utf-8" /&gt;
+ &lt;/head&gt;
+
+ &lt;body&gt;
+ &lt;script src="page-scripts/page-script.js"&gt;&lt;/script&gt;
+ &lt;/body&gt;
+&lt;/html&gt;</pre>
+
+<p>脚本文件“page-script.js”如下:</p>
+
+<pre class="brush: js">// page-script.js
+
+// add a new element to the DOM
+var p = document.createElement("p");
+p.textContent = "This paragraph was added by a page script.";
+p.setAttribute("id", "page-script-para");
+document.body.appendChild(p);
+
+// define a new property on the window
+window.foo = "This global variable was added by a page script";
+
+// redefine the built-in window.confirm() function
+window.confirm = function() {
+ alert("The page script has also redefined 'confirm'");
+}</pre>
+
+<p>现在一个扩展插入一个content script 如下:</p>
+
+<pre class="brush: js">// content-script.js
+
+// can access and modify the DOM
+var pageScriptPara = document.getElementById("page-script-para");
+pageScriptPara.style.backgroundColor = "blue";
+
+// can't see page-script-added properties
+console.log(window.foo); // undefined
+
+// sees the original form of redefined properties
+window.confirm("Are you sure?"); // calls the original window.confirm()</pre>
+
+<p>相反的情况也是成立的:页面脚本不能察觉到通过content scripts 添加的JavaScript 属性。</p>
+
+<p>这意味着content script 可以依靠DOM属性获取可预期的行为</p>
+
+<p>这种行为造成的一个结果是content script不能获取任何通过页面加载的Javascript 库。所以,如果这个页面包含JQuery,content script 将不会在意它。</p>
+
+<p>如果一个content script 想要使用Javascript库,这个库本身就必须像一个content script一样在这个content script旁被插入:</p>
+
+<pre class="brush: json">"content_scripts": [
+ {
+ "matches": ["*://*.mozilla.org/*"],
+ "js": ["jquery.js", "content-script.js"]
+ }
+]</pre>
+
+<h3 id="WebExtension_APIs">WebExtension APIs</h3>
+
+<p>除了standard DOM APIS,content script还能使用以下WebExtension APIS:</p>
+
+<p>From <code><a href="/en-US/Add-ons/WebExtensions/API/extension">extension</a></code>:</p>
+
+<ul>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/API/extension#getURL()">getURL()</a></code></li>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/API/extension#inIncognitoContext">inIncognitoContext</a></code></li>
+</ul>
+
+<p>From <code><a href="/en-US/Add-ons/WebExtensions/API/runtime">runtime</a></code>:</p>
+
+<ul>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#connect()">connect()</a></code></li>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#getManifest()">getManifest()</a></code></li>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#getURL()">getURL()</a></code></li>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#onConnect">onConnect</a></code></li>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#onMessage">onMessage</a></code></li>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#sendMessage()">sendMessage()</a></code></li>
+</ul>
+
+<p>From <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n">i18n</a></code>:</p>
+
+<ul>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n/getMessage">getMessage()</a></code></li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n/getAcceptLanguages">getAcceptLanguages()</a></code></li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n/getUILanguage">getUILanguage()</a></code></li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n/detectLanguage">detectLanguage()</a></code></li>
+</ul>
+
+<p>所有 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage">storage</a></code>.</p>
+
+<h3 id="跨域名权限">跨域名权限</h3>
+
+<p>content scripts 拥有与扩展剩余部分一致的权限:所以如果这个扩展已在manifest.json文件中使用permission关键字请求跨域权限,其content script将能很好获取某些跨域权限。</p>
+
+<h2 id="后台脚本通信">后台脚本通信</h2>
+
+<p>尽管content scripts 不能直接使用大部分WebExtension APIS,但他们可以通过使用messaging APIS 与扩展的后台脚本通信,然后便能够间接地调用所有的后台脚本能够调用的APIS。</p>
+
+<p>在background script和content script中有两种基本的通讯方式:你可以发送带有可选回复的一次性的消息,或者在两者之间建立一个长期活动的连接并用这个连接来进行信息交换。</p>
+
+<h3 id="一次性消息">一次性消息</h3>
+
+<p>为了发送一个带有可选回复选项的一次性消息,你能使用以下APIS:</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="row"> </th>
+ <th scope="col">In content script</th>
+ <th scope="col">In background script</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <th scope="row">Send a message</th>
+ <td><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#sendMessage()">browser.runtime.sendMessage()</a></code></td>
+ <td><code><a href="/en-US/Add-ons/WebExtensions/API/Tabs/sendMessage">browser.tabs.sendMessage()</a></code></td>
+ </tr>
+ <tr>
+ <th scope="row">Receive a message</th>
+ <td><code><a href="/en-US/Add-ons/WebExtensions/API/runtime/onMessage">browser.runtime.onMessage</a></code></td>
+ <td><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#onMessage">browser.runtime.onMessage</a></code></td>
+ </tr>
+ </tbody>
+</table>
+
+<p>举例,这里是一个监听点击事件的content script,如果点击发生在一个链接上,他将会将该链接的地址发送给后台脚本:</p>
+
+<pre class="brush: js">// content-script.js
+
+window.addEventListener("click", notifyExtension);
+
+function notifyExtension(e) {
+ if (e.target.tagName != "A") {
+ return;
+ }
+ browser.runtime.sendMessage({"url": e.target.href});
+}</pre>
+
+<p>后台脚本监听这个消息然后使用<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/notifications">notifications</a></code> API 显示一个通知:</p>
+
+<pre class="brush: js">// background-script.js
+
+browser.runtime.onMessage.addListener(notify);
+
+function notify(message) {
+ browser.notifications.create({
+ "type": "basic",
+ "iconUrl": browser.extension.getURL("link.png"),
+ "title": "You clicked a link!",
+ "message": message.url
+ });
+}
+</pre>
+
+<p>这个示范代码从Github上的 <a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a> 例子 修改而来.</p>
+
+<h3 id="Connection-based_messaging">Connection-based messaging</h3>
+
+<p>如果你将在一个content script 和 后台脚本间交换大量的消息,一次性消息会变得笨重而缓慢。所以一个更好的方案是在两个脚本间建立一个长久连接,然后使用该连接交换消息。</p>
+
+<p>每个脚本都有一个 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port">runtime.Port</a></code> 对象用以交换消息。</p>
+
+<p>建立过程::</p>
+
+<ul>
+ <li>
+ <p>在一个脚本中使用 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onConnect">runtime.onConnect</a></code> 监听连接</p>
+ </li>
+ <li>另一个脚本中调用 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/connect">tabs.connect()</a></code> (如果连接 content script) or <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connect">runtime.connect()</a></code> (如果连接后台脚本). 这会返回一个 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port">runtime.Port</a></code> 对象.</li>
+ <li> <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onConnect">runtime.onConnect</a></code>  传递它自己的 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/Port">runtime.Port</a></code> 对象.</li>
+</ul>
+
+<p>每个脚本都拥有一个port,两个脚本可以使用runtime.Port.postMessage()来发送消息,runtime.Port.onMessage 来接收消息</p>
+
+<p>比如,当加载该content script时:</p>
+
+<ul>
+ <li>连接到后台脚本,存取Port对象至 <code>myPort</code></li>
+ <li>监听myPort上的消息,并记录。</li>
+ <li>当用户点击网页是发送消息至后台脚本。</li>
+</ul>
+
+<pre class="brush: js">// content-script.js
+
+var myPort = browser.runtime.connect({name:"port-from-cs"});
+myPort.postMessage({greeting: "hello from content script"});
+
+myPort.onMessage.addListener(function(m) {
+ console.log("In content script, received message from background script: ");
+ console.log(m.greeting);
+});
+
+document.body.addEventListener("click", function() {
+ myPort.postMessage({greeting: "they clicked the page!"});
+});</pre>
+
+<p>对应的后台脚本:</p>
+
+<ul>
+ <li>监听content script 的所有连接企图。</li>
+ <li>当收到连接请求后:
+ <ul>
+ <li>存贮Port对象至 <code>portFromCS</code></li>
+ <li>使用portFromCS发送一个消息到content script</li>
+ <li>开始监听消息并记录它们。</li>
+ </ul>
+ </li>
+ <li>当用户点击浏览器的某些扩展按钮或动作后,发送一个消息到content script。</li>
+</ul>
+
+<pre class="brush: js">// background-script.js
+
+var portFromCS;
+
+function connected(p) {
+ portFromCS = p;
+ portFromCS.postMessage({greeting: "hi there content script!"});
+ portFromCS.onMessage.addListener(function(m) {
+ console.log("In background script, received message from content script")
+ console.log(m.greeting);
+ });
+}
+
+browser.runtime.onConnect.addListener(connected);
+
+browser.browserAction.onClicked.addListener(function() {
+ portFromCS.postMessage({greeting: "they clicked the button!"});
+});
+</pre>
+
+<p> <a href="https://github.com/mdn/webextensions-examples/tree/master/inpage-toolbar-ui">inpage-toolbar-ui</a> 例子使用了 connection-based messaging.</p>
+
+<ul>
+</ul>
+
+<h2 id="网页通信">网页通信</h2>
+
+<p>尽管content script 通常不能获取由网页脚本创建的对象,但他们可以通过 <code><a href="/en-US/docs/Web/API/Window/postMessage">window.postMessage</a></code> 和 <code><a href="/en-US/docs/Web/API/EventTarget/addEventListener">window.addEventListener</a></code> APIs 与网页脚本进行通信.</p>
+
+<p>比如:</p>
+
+<pre class="brush: js">// page-script.js
+
+var messenger = document.getElementById("from-page-script");
+
+messenger.addEventListener("click", messageContentScript);
+
+function messageContentScript() {
+ window.postMessage({
+ direction: "from-page-script",
+ message: "Message from the page"
+ }, "*");</pre>
+
+<pre class="brush: js">// content-script.js
+
+window.addEventListener("message", function(event) {
+ if (event.source == window &amp;&amp;
+ event.data.direction &amp;&amp;
+ event.data.direction == "from-page-script") {
+ alert("Content script received message: \"" + event.data.message + "\"");
+ }
+});</pre>
+
+<p>完整的例子请访问该链接, <a href="https://mdn.github.io/webextensions-examples/content-script-page-script-messaging.html">visit the demo page on GitHub</a> 并且观看以下介绍.</p>
+
+<div class="warning">
+<p>需要注意的是当你用该方法与一些不被信任的网页进行交互式需要特别小心。WebExtensions拥有高等级权限,而一些恶意页面可以很轻松的获取这些权限。</p>
+
+<p>做一个微小的示范,假定有如下content script 代码:</p>
+
+<pre class="brush: js">// content-script.js
+
+window.addEventListener("message", function(event) {
+ if (event.source == window &amp;&amp;
+ event.data.direction &amp;&amp;
+ event.data.direction == "from-page-script") {
+ eval(event.data.message);
+ }
+});</pre>
+
+<p>现在网页脚本可以在content script 权限范围内运行任何代码。</p>
+</div>
+
+<h2 id="与页面脚本共享对象">与页面脚本共享对象</h2>
+
+<div class="note">
+<p>这个部分的技术描述只适用于49版本后的Firefox</p>
+</div>
+
+<div class="warning">
+<p>作为一个插件开发者你必须考虑脚本运行在任何伺机偷取用户个人隐私,破坏他们的电脑,或者使用其他方式攻击的网页上。</p>
+
+<p>隔离content script 和 页面脚本 便是为了使恶意网页的攻击变得更加困难。</p>
+
+<p>这部分的技术打破了这个隔离,它们从根本上是危险的而应该被谨慎使用。</p>
+</div>
+
+<p>我们在 <a href="/en-US/Add-ons/WebExtensions/Content_scripts#DOM_access">DOM access</a> 中看到content scripts不会察觉到通过网页脚本修改的某些属性. 这意味着,如果一个网页加载了一个库比如JQuery,content script 将不会使用它,而不得不加载它自己的一个复制。相反的,网页加载的脚本也不能获知content script的修改。</p>
+
+<p>然而,Firefox提供了一些APIS 可以使得content script能够:</p>
+
+<ul>
+ <li>访问页面脚本创建的Javascript 对象</li>
+ <li>暴露他们自己的JavaScript对象给页面脚本.</li>
+</ul>
+
+<h3 id="Xray_vision_in_Firefox">Xray vision in Firefox</h3>
+
+<p>在Firefox中,隔离content script 和页面脚本通过使用一种称为“Xray vision”的功能实现。 当一个处于更高权限的脚本访问一个被定义于一个更低权限版本的域中时,它将只能看见这个对象的原始版本。</p>
+
+<p>任何 <a href="/en-US/docs/Glossary/Expando">expando</a> 属性都是不可见得, 而且如果对象的任何属性被重定义,他也只能能看见原始的实现而不是重定义的实现。</p>
+
+<p>这个功能的目的是为了让低权限的脚本不至于因为重定义原始对象属性而使高权限脚本行为异常。</p>
+
+<p>让我们来举个例子,当一个content script 访问一个页面的 <a href="/en-US/docs/Web/API/Window">window</a> 类,他不会看见任何该页面脚本对这个window 添加的任何属性, 如果页面脚本重定义了任何已存在的属性,content script将只能看见该属性的原始版本。</p>
+
+<p>更多信心请查看 <a href="/en-US/docs/Mozilla/Tech/Xray_vision">Xray vision</a> 和 <a href="/en-US/docs/Mozilla/Gecko/Script_security">Script security</a>.</p>
+
+<h3 id="从content_script_中访问_页面脚本对象">从content script 中访问 页面脚本对象</h3>
+
+<p>在Firefox中,content script中的DOM对象会获得一个额外的属性 wrappedJSObject。这是一个会包含任何由页面脚本所造成修改的”未包裹“对象。</p>
+
+<p>让我们来看一个简单的例子,假定一个页面载入脚本如下:</p>
+
+<pre class="brush: html">&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;meta charset="UTF-8"&gt;
+ &lt;/head&gt;
+ &lt;body&gt;
+ &lt;script type="text/javascript" src="main.js"&gt;&lt;/script&gt;
+ &lt;/body&gt;
+&lt;/html&gt;</pre>
+
+<p><code>这个脚本添加一个全局的属性到全局window</code>:</p>
+
+<pre class="brush: js">// main.js
+
+var foo = "I'm defined in a page script!";</pre>
+
+<p>Xray vision 意味着 如果一个content script 尝试访问foo,它将是未定义的:</p>
+
+<pre class="brush: js">// content-script.js
+
+console.log(window.foo); // undefined</pre>
+
+<p>在Firefox,content script 可以使用window.wrappedJSObject来看见全局属性:</p>
+
+<pre class="brush: js">// content-script.js
+
+console.log(window.wrappedJSObject.foo); // "I'm defined in a page script!"</pre>
+
+<p>注意因为这个原因,你最好不在依赖该对象的任何属性或方法 建立或执行某些操作,你所期望的,它们,甚至setter和getter 都可能被不被信任的代码重定义。</p>
+
+<p>同时注意unwarapping是及物的:当你使用wrappedJSObject,该未包裹对象的任何属性都是未包裹的(同时都是不可靠的),所以 一个好的建议是只在你需要时获取这个对象,重新包裹他,你能这样做:</p>
+
+<pre class="bz_comment_text" id="comment_text_38">XPCNativeWrapper(window.wrappedJSObject.foo);</pre>
+
+<p>查看 <a href="/en-US/docs/Mozilla/Tech/Xray_vision">Xray vision </a>  文档获取更多.</p>
+
+<h3 id="与页面脚本共享content_script_对象">与页面脚本共享content script 对象</h3>
+
+<p>Firefox 同样提供APIS允许content scripts 是对象对于页面脚本可用。这里是两个主要的APIS:</p>
+
+<ul>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/Content_scripts#exportFunction">exportFunction()</a></code>: 导出一个函数至页面脚本</li>
+ <li><code><a href="/en-US/Add-ons/WebExtensions/Content_scripts#cloneInto">cloneInto()</a></code>: 导出一个对象至页面脚本</li>
+</ul>
+
+<h4 id="exportFunction">exportFunction</h4>
+
+<p>给予一个定义于content script中的方法,exportFunction()导出他至页面脚本域,然后脚本可以调用它。</p>
+
+<p>比如,让我们考虑一个WebExtension有一个后台脚本如下:</p>
+
+<pre class="brush: js">/*
+Execute content script in the active tab.
+*/
+function loadContentScript() {
+ browser.tabs.executeScript({
+ file: "/content_scripts/export.js"
+ });
+}
+
+/*
+Add loadContentScript() as a listener to clicks
+on the browser action.
+*/
+browser.browserAction.onClicked.addListener(loadContentScript);
+
+/*
+Show a notification when we get messages from
+the content script.
+*/
+browser.runtime.onMessage.addListener((message) =&gt; {
+ browser.notifications.create({
+ type: "basic",
+ title: "Message from the page",
+ message: message.content
+ });
+});</pre>
+
+<p>该脚本做了两件事:</p>
+
+<ul>
+ <li>当用户点击浏览器按钮时,在当前标签执行一个content script 。</li>
+ <li>监听从content script 传递的消息,并在消息到达时显示一个通知。</li>
+</ul>
+
+<p>content script 如下:</p>
+
+<pre class="brush: js">/*
+Define a function in the content script's scope, then export it
+into the page script's scope.
+*/
+function notify(message) {
+ browser.runtime.sendMessage({content: "Function call: " + message});
+}
+
+exportFunction(notify, window, {defineAs:'notify'});</pre>
+
+<p>该脚本定义了一个函数notify()用以发送其参数到后台脚本,而后他导出了这个函数至页面脚本域。现在页面脚本可以调用该函数:</p>
+
+<pre class="brush: js">window.notify("Message from the page script!");</pre>
+
+<p>更详细的信息请看, <code><a href="/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction">Components.utils.exportFunction</a></code>.</p>
+
+<h4 id="cloneInto">cloneInto</h4>
+
+<p>给予一个定义于content script的对象, 该技术可以创建该对象的一个复制到页面脚本域,从而使该复制可以被页面脚本访问.通常使用 <a href="/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm">structured clone algorithm</a> 复制对象, 这意味着该对象中的方法不会被复制为了复制方法,需要传递cloneFunction选项.</p>
+
+<p>比如,这里有一个content script 定义了一个包含方法的对象,然后复制他们至页面脚本域:</p>
+
+<pre class="brush: js">/*
+Create an object that contains functions in
+the content script's scope, then clone it
+into the page script's scope.
+
+Because the object contains functions,
+the cloneInto call must include
+the `cloneFunctions` option.
+*/
+var messenger = {
+ notify: function(message) {
+ browser.runtime.sendMessage({
+ content: "Object method call: " + message
+ });
+ }
+};
+
+window.wrappedJSObject.messenger = cloneInto(
+ messenger,
+ window,
+ {cloneFunctions: true});</pre>
+
+<p><code>现在页面脚本将看到新的含有notify方法的属性</code>:</p>
+
+<pre class="brush: js">window.messenger.notify("Message from the page script!");</pre>
+
+<p>详情请看 <code><a href="/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.cloneInto">Components.utils.cloneInto</a></code>.</p>
+
+<h2 id="在content_script中使用_eval()">在content script中使用 eval()</h2>
+
+<p>在 Chrome中,<code>eval()</code> 总是在content script的上下文环境中运行, 而不是在页面的上下文环境中运行.</p>
+
+<p>在Firefox中:</p>
+
+<ul>
+ <li>如果你调用<code>eval()</code>,它在content script的上下文中运行</li>
+ <li>如果你调用<code>window.eval()</code>,它在页面的上下文中运行</li>
+</ul>
+
+<p>比如,有一个content script如下:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="comment token">// content-script.js</span>
+
+window<span class="punctuation token">.</span><span class="function token">eval</span><span class="punctuation token">(</span><span class="string token">'window.x = 1;'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="function token">eval</span><span class="punctuation token">(</span><span class="string token">'window.y = 2'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="template-string token"><span class="string token">`In content script, window.x: </span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span>window<span class="punctuation token">.</span>x<span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">`</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="template-string token"><span class="string token">`In content script, window.y: </span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span>window<span class="punctuation token">.</span>y<span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">`</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+
+window<span class="punctuation token">.</span><span class="function token">postMessage</span><span class="punctuation token">(</span><span class="punctuation token">{</span>
+ message<span class="punctuation token">:</span> <span class="string token">"check"</span>
+<span class="punctuation token">}</span><span class="punctuation token">,</span> <span class="string token">"*"</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>这段代码仅仅通过调用<code>window.eval()</code> 和 <code>eval()</code>创建了变量x和y。然后记录它们的值并通知页面更新.</p>
+
+<p>接收到消息后页面的脚本记录下这些变量:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js">window<span class="punctuation token">.</span><span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">"message"</span><span class="punctuation token">,</span> <span class="keyword token">function</span><span class="punctuation token">(</span>event<span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ <span class="keyword token">if</span> <span class="punctuation token">(</span>event<span class="punctuation token">.</span>source <span class="operator token">===</span> window <span class="operator token">&amp;&amp;</span> event<span class="punctuation token">.</span>data <span class="operator token">&amp;&amp;</span> event<span class="punctuation token">.</span>data<span class="punctuation token">.</span>message <span class="operator token">===</span> <span class="string token">"check"</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="template-string token"><span class="string token">`In page script, window.x: </span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span>window<span class="punctuation token">.</span>x<span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">`</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="template-string token"><span class="string token">`In page script, window.y: </span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span>window<span class="punctuation token">.</span>y<span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">`</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+ <span class="punctuation token">}</span>
+<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>在Chrome中,输出类似下面所示:</p>
+
+<pre class="line-numbers language-html"><code class="language-html">In content script, window.x: 1
+In content script, window.y: 2
+In page script, window.x: undefined
+In page script, window.y: undefined</code></pre>
+
+<p>在Firefox中,输出类似下面所示:</p>
+
+<pre class="line-numbers language-html"><code class="language-html">In content script, window.x: undefined
+In content script, window.y: 2
+In page script, window.x: 1
+In page script, window.y: undefined</code></pre>
+
+<p>上述内容同样适用于 <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code>, <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval">setInterval()</a></code>, and <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function">Function()</a></code>.</p>
+
+<p>当在页面的上下文中运行代码时, 适用于上面所提到的"<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_scripts#Sharing_objects_with_page_scripts">Sharing content script objects with page scripts</a>" 这一部分的警告: 页面的环境可能会被恶意的网页所控制,这可能会导致你所交互的对象会有意想不到的行为:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="comment token">// page.js redefines console.log</span>
+
+<span class="keyword token">var</span> original <span class="operator token">=</span> console<span class="punctuation token">.</span>log<span class="punctuation token">;</span>
+
+console<span class="punctuation token">.</span>log <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ <span class="function token">original</span><span class="punctuation token">(</span><span class="keyword token">true</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}</span></code></pre>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="comment token">// content-script.js calls the redefined version</span>
+
+window<span class="punctuation token">.</span><span class="function token">eval</span><span class="punctuation token">(</span><span class="string token">'console.log(false)'</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/content_security_policy/index.html b/files/zh-cn/mozilla/add-ons/webextensions/content_security_policy/index.html
new file mode 100644
index 0000000000..7ea0d2655d
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/content_security_policy/index.html
@@ -0,0 +1,107 @@
+---
+title: Content Security Policy
+slug: Mozilla/Add-ons/WebExtensions/Content_Security_Policy
+translation_of: Mozilla/Add-ons/WebExtensions/Content_Security_Policy
+---
+<div>{{AddonSidebar}}</div>
+
+<div class="summary">
+<p>使用WebExtension API 开发的插件默认应用了内容安全策略(Content Security Policy, 缩写CSP)。这限制了可以加载的<strong><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script"> </a></strong><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script">&lt;script&gt;</a> 和 <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/object">&lt;object&gt;</a> 的资源来源,并且禁止了潜在的不安全用法如 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval">eval()</a></code>.</p>
+
+<p>这篇文章简单地解释了CSP是什么,默认的策略是什么,这对插件来说意味着什么,以及插件如何改变默认CSP。</p>
+</div>
+
+<p><a href="/en-US/docs/Web/HTTP/CSP">Content Security Policy</a> (CSP) 是一种避免网站意外执行包含有恶意的内容的机制。网站通过使用服务端发送的HTTP头指定CSP。CSP主要关注指定各种内容的合法来源,如脚本和嵌入式插件。例如,网站可以使用它来告诉浏览器应该只执行来自网站自身的JavaScript,而不腻执行其他来源的脚本。CSP还可以指导浏览器禁止潜在危险行为,如<code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval">eval()</a></code>的使用。</p>
+
+<p>和网页一样,插件可以加载其他来源的内容。例如浏览器的弹出窗口可以指定为一个HTML文档,它同样可以包含不同来源的JavaScript和CSS,就像一个普通的网页一样。</p>
+
+<pre class="brush: html">&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;meta charset="utf-8"&gt;
+ &lt;/head&gt;
+
+ &lt;body&gt;
+
+ &lt;!--Some HTML content here--&gt;
+
+ &lt;!--
+ Include a third-party script.
+ See also https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity.
+ --&gt;
+ &lt;script
+ src="https://code.jquery.com/jquery-2.2.4.js"
+ integrity="sha256-iT6Q9iMJYuQiMWNd9lDyBUStIq/8PuOW33aOqmvFpqI="
+ crossorigin="anonymous"&gt;
+ &lt;/script&gt;
+
+ &lt;!-- Include my popup's own script--&gt;
+ &lt;script src="popup.js"&gt;&lt;/script&gt;
+ &lt;/body&gt;
+
+&lt;/html&gt;</pre>
+
+<p>和网站相比,插件可以访问特权API,因此一旦它们被恶意代码破坏,风险就更大。因此:</p>
+
+<ul>
+ <li>插件默认运行在一个相当严格的安全策略下。参考 <a href="/en-US/Add-ons/WebExtensions/Content_Security_Policy#Default_content_security_policy">default content security policy</a>.</li>
+ <li>插件的作者可以通过使用manifest.json中的 <code>content_security_policy</code> 关键词改变这种默认策略,但是允许的策略仍然有一定的限制。参考 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_security_policy">content_security_policy</a></code>.</li>
+</ul>
+
+<h2 id="默认内容安全策略">默认内容安全策略</h2>
+
+<p>对插件的默认内容安全策略如下:</p>
+
+<pre>"script-src 'self'; object-src 'self';"</pre>
+
+<p>这会被应用在任何没有明确在manifest.json中的<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_security_policy">content_security_policy</a></code> 项设置自己的内容安全策略的插件中。它有以下几种效果:</p>
+
+<ul>
+ <li>
+ <p><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_Security_Policy#Location_of_script_and_object_resources">你只能将本地的 &lt;script&gt; 和 &lt;object&gt; 资源加载到插件中。</a></p>
+ </li>
+ <li>
+ <p><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_Security_Policy#eval()_and_friends">插件无法将字符串转换为JavaScript执行。</a></p>
+ </li>
+ <li>
+ <p><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Content_Security_Policy#Inline_JavaScript">内联JavaScript不会被执行。</a></p>
+ </li>
+</ul>
+
+<h3 id="script_和_object资源的位置">script 和 object资源的位置</h3>
+
+<p>在默认CSP下你只能加载相对插件来说本地的 <a href="/en-US/docs/Web/HTML/Element/script">&lt;script&gt;</a> 和 <a href="/en-US/docs/Web/HTML/Element/object">&lt;object&gt;</a> 资源。例如假设插件文档中存在这样一条语句:</p>
+
+<pre class="brush: html"> &lt;script src="https://code.jquery.com/jquery-2.2.4.js"&gt;&lt;/script&gt;</pre>
+
+<p>这不会加载请求的资源:它会安静地失败,并且你所期望看到的任何来自该资源的对象都不会出现。对于这种情况有两种解决办法:</p>
+
+<ul>
+ <li>
+ <p>下载该资源,打包进你的插件,然后引用它。</p>
+ </li>
+ <li>
+ <p>使用 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_security_policy">content_security_policy</a></code> 允许你所需要的资源。</p>
+ </li>
+</ul>
+
+<h3 id="eval_和friends">eval() 和friends</h3>
+
+<p>默认CSP下插件不被允许像JavaScript一样执行字符串。这意味着以下情况都被禁止:</p>
+
+<pre class="brush: js">eval("console.log('some output');");</pre>
+
+<pre class="brush: js">window.setTimeout("alert('Hello World!');", 500);</pre>
+
+<pre class="brush: js">var f = new Function("console.log('foo');");</pre>
+
+<h3 id="内联_JavaScript">内联 JavaScript</h3>
+
+<p>默认CSP下内联JavaScript不被执行。这不仅不允许将JavaScript直接放在 <code>&lt;script&gt;</code> 标签中间,也不允许内联事件句柄。即以下内容被禁止:</p>
+
+<pre class="brush: html">&lt;script&gt;console.log("foo");&lt;/script&gt;</pre>
+
+<pre class="brush: html">&lt;div onclick="console.log('click')"&gt;Click me!&lt;/div&gt;</pre>
+
+<p>如果你正在使用类似 <code>&lt;body onload="main()"&gt;</code> 的代码在页面加载时运行你的脚本,请使用监听器监听<a href="/en-US/docs/Web/Events/DOMContentLoaded">DOMContentLoaded</a> 或者 <a href="/en-US/docs/Web/Events/load">load</a> 代替。</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/embedded_webextensions/index.html b/files/zh-cn/mozilla/add-ons/webextensions/embedded_webextensions/index.html
new file mode 100644
index 0000000000..834125bb32
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/embedded_webextensions/index.html
@@ -0,0 +1,205 @@
+---
+title: Embedded WebExtensions
+slug: Mozilla/Add-ons/WebExtensions/Embedded_WebExtensions
+translation_of: Archive/Add-ons/Embedded_WebExtensions
+---
+<div>{{AddonSidebar}}</div>
+
+<div class="note">
+<p>嵌入一个 WebExtension 需要使用 Firefox 51 或更高版本。在 SDK 附加组件中嵌入一个 WebExtension 还需要 <a href="https://www.npmjs.com/package/jpm">jpm 1.2.0</a>。</p>
+</div>
+
+<p>从 Firefox 51 开始,你可以在传统附加组件类型中嵌入一个 WebExtension。</p>
+
+<p>传统附加组件可以是经典的<a href="/en-US/docs/Mozilla/Add-ons/Bootstrapped_extensions">自举扩展</a>或者<a href="/en-US/docs/Mozilla/Add-ons/SDK">Add-on SDK</a> 附加组件。嵌入式 WebExtension 的文件打包在传统附加组件中。嵌入式 WebExtension 并不直接与嵌入的附加组件共享范围,但可以使用 {{WebExtAPIRef("runtime")}} API 中定义的消息函数交换消息。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/13895/embedded-we.png" style="display: block; height: 522px; margin-left: auto; margin-right: auto; width: 429px;"></p>
+
+<p>这意味着您可以一次性迁移传统附加组件到 WebExtensions,并且在此期间附加组件的功能完全保留。尤其是它可以让您从旧版附加组件<a href="/en-US/Add-ons/WebExtensions/Embedded_WebExtensions#Migrating_data_from_legacy_add-ons">迁移存储数据</a>到 WebExtension,通过撰写一个中间的混合式附加组件,使用旧版 API 读取数据(例如 <a href="/en-US/docs/Mozilla/Add-ons/SDK/High-Level_APIs/simple-prefs">simple-prefs</a> 或 preferences <a href="/en-US/docs/Mozilla/JavaScript_code_modules/Services.jsm">服务</a>)并使用 WebExtension API 写入它(例如 {{WebExtAPIRef("storage")}})。</p>
+
+<p>连同本指南,我们撰写了两个例子展示如何使用嵌入式 WebExtensions 来帮助从传统附加组件迁移。<a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-bootstrapped">如何从自举式附加组件迁移</a>以及<a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-sdk">如何从 SDK 附加组件迁移</a>。</p>
+
+<h2 id="嵌入_WebExtension">嵌入 WebExtension</h2>
+
+<p>如果传统附加组件是一个带有<a href="/en-US/Add-ons/Install_Manifests">install.rdf</a> 的自举式扩展,在该 RDF 中加入 "hasEmbeddedWebExtension" 并设为 "true":</p>
+
+<pre>&lt;<span class="pl-ent">em</span><span class="pl-ent">:</span><span class="pl-ent">hasEmbeddedWebExtension</span>&gt;true&lt;/<span class="pl-ent">em</span><span class="pl-ent">:</span><span class="pl-ent">hasEmbeddedWebExtension</span>&gt;</pre>
+
+<div>如果旧式附加组件是一个 SDK 附加组件,在 package.json 中包含 "hasEmbeddedWebExtension" 并设为 <code>true</code>:</div>
+
+<div> </div>
+
+<pre class="brush: json"><span class="pl-s"><span class="pl-pds">"</span>hasEmbeddedWebExtension<span class="pl-pds">"</span></span>: <span class="pl-c1">true</span>
+</pre>
+
+<div>WebExtension 本身放在附加组件中的 "webextension" 顶层目录。例如:</div>
+
+<div> </div>
+
+<pre>my-boostrapped-addon/
+ chrome/
+ webextension/
+ manifest.json
+ background.js
+ ...
+ bootstrap.js
+ chrome.manifest
+ install.rdf</pre>
+
+<div> </div>
+
+<div>
+<pre>my-sdk-addon/
+ index.js
+ package.json
+ webextension/
+ manifest.json
+ background.js
+ ...</pre>
+</div>
+
+<p>Firefox 不将嵌入式 WebExtension 视为一个独立的附加组件。因此,您不应该为它指定一个<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID">附加组件 ID</a>。如果你这样做,那只会被忽略。</p>
+
+<p>但是,在您完成附加组件的迁移并移除旧式嵌入代码后,您必须添加一个 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications">applications</a> 键,设置 ID 为旧式附加组件的 ID。通过此方式,<a href="https://addons.mozilla.org/en-US/firefox/">addons.mozilla.org</a> 可以识别 WebExtension 是旧式附加组件的一个更新。</p>
+
+<h2 id="启动_WebExtension">启动 WebExtension</h2>
+
+<p>嵌入式 WebExtension 必须由被嵌入的附加组件明确启动。</p>
+
+<p>如果被嵌入的附加组件是一个自举式附加组件,那么传递到自举式扩展的 <code><a href="/en-US/Add-ons/Bootstrapped_extensions#startup">startup()</a></code> 函数的 <code>data</code> 将获得一个明确的 <code>webExtension</code>:</p>
+
+<pre class="brush: js">// bootstrapped add-on
+
+<span class="pl-k">function</span> <span class="pl-en">startup</span>({webExtension}) {
+
+...</pre>
+
+<p>如果被嵌入的附加组件是一个 SDK 附加组件,它可以使用 <code>sdk/webextension</code> 模块访问一个 WebExtension 对象:</p>
+
+<pre class="brush: js"><span class="pl-k">// SDK add-on
+
+const</span> <span class="pl-c1">webExtension</span> <span class="pl-k">=</span> <span class="pl-c1">require</span>(<span class="pl-s"><span class="pl-pds">"</span>sdk/webextension<span class="pl-pds">"</span></span>);</pre>
+
+<p>无论哪种方式,此对象都有一个 <code>startup()</code> 函数,它返回一个 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a></code>。该 promise 使用一个 <code>browser</code> 属性解决一个对象:这包括 {{WebExtAPIRef("runtime")}} API,被嵌入的附加组件可以用它来与嵌入式 WebExtension 交换消息:</p>
+
+<ul>
+ <li>{{WebExtAPIRef("runtime.onConnect")}}</li>
+ <li>{{WebExtAPIRef("runtime.onMessage")}}</li>
+</ul>
+
+<p>例如:</p>
+
+<pre class="brush: js">// bootstrapped add-on
+
+function startup({webExtension}) {
+ webExtension.startup().then(api =&gt; {
+ const {browser} = api;
+ browser.runtime.onMessage.addListener(handleMessage);
+ });
+}</pre>
+
+<pre class="brush: js"><span class="pl-k">// SDK add-on</span>
+
+const webExtension = require("sdk/webextension");
+
+webExtension.startup().then(api =&gt; {
+ const {browser} = api;
+ browser.runtime.onMessage.addListener(handleMessage);
+});
+</pre>
+
+<p>应注意的是,嵌入的附加组件不能启动通信,它可以使用 <code>onMessage</code> 接收(并可选响应)一次性消息,并可以使用 <code>onConnect</code> 接受连接请求。</p>
+
+<p>如果嵌入式 WebExtension 缺少一个 manifest,或者如果 manifest 无效,该 promise 会被拒绝。这种情况下,您可以在<a href="/en-US/Add-ons/WebExtensions/Debugging#Viewing_log_output">浏览器工具箱的控制台</a>中看到更多细节。</p>
+
+<h2 id="交换消息">交换消息</h2>
+
+<p>一旦嵌入式 WebExtension 处在运行,它可以使用 {{WebExtAPIRef("runtime")}} API 的子集与旧式附加组件交换消息:</p>
+
+<ul>
+ <li>它可以使用 {{WebExtAPIRef("runtime.sendMessage()")}} 发送一次性消息。</li>
+ <li>它可以使用 {{WebExtAPIRef("runtime.connect()")}} 建立一个连接。</li>
+</ul>
+
+<h3 id="无需连接的消息">无需连接的消息</h3>
+
+<p>要发送一条消息,WebExtension 可以使用 {{WebExtAPIRef("runtime.sendMessage()")}}。您可以省略 <code>extensionId</code> 参数,因为浏览器认为嵌入式 WebExtension 是被嵌入附加组件的一部分:</p>
+
+<pre class="brush: js">browser.runtime.sendMessage("message-from-webextension").then(reply =&gt; {
+ if (reply) {
+ console.log("response from legacy add-on: " + reply.content);
+ }
+});</pre>
+
+<p>被嵌入的附加组件可以使用 {{WebExtAPIRef("runtime.onMessage")}} 对象接收消息(并可选响应):</p>
+
+<pre class="brush: js">// bootstrapped add-on
+
+function startup({webExtension}) {
+ // Start the embedded webextension.
+ webExtension.startup().then(api =&gt; {
+ const {browser} = api;
+ browser.runtime.onMessage.addListener((msg, sender, sendReply) =&gt; {
+ if (msg == "message-from-webextension") {
+ sendReply({
+ content: "reply from legacy add-on"
+ });
+ }
+ });
+ });
+}</pre>
+
+<h3 id="基于连接的消息">基于连接的消息</h3>
+
+<p>要在 WebExtension 与传统附加组件间设置一个长寿命连接,WebExtension 可以使用 {{WebExtAPIRef("runtime.connect()")}}。</p>
+
+<pre class="brush: js">var port = browser.runtime.connect({name: "connection-to-legacy"});
+
+port.onMessage.addListener(function(message) {
+ console.log("Message from legacy add-on: " + message.content);
+});
+</pre>
+
+<p>旧式附加组件可以使用 {{WebExtAPIRef("runtime.onConnect")}} 监听连接尝试,双方可以使用得到的 {{webExtAPIRef("runtime.Port")}} 来交换消息:</p>
+
+<pre class="brush: js">function startup({webExtension}) {
+ // Start the embedded webextension.
+ webExtension.startup().then(api =&gt; {
+ const {browser} = api;
+ browser.runtime.onConnect.addListener((port) =&gt; {
+ port.postMessage({
+ content: "content from legacy add-on"
+ });
+ });
+ });
+}</pre>
+
+<h2 id="从传统附加组件迁移数据">从传统附加组件迁移数据</h2>
+
+<p>嵌入式 WebExtensions 的一项主要用途是迁移附加组件的存储数据。</p>
+
+<p>人们从旧式附加组件类型迁移的一个主要问题是存储数据,因为旧式附加组件不能使用 WebExtension 存储 API,WebExtensions 也不能使用旧式存储 API。例如,如果一个 SDK 附加组件使用了 SDK 的 <a href="/en-US/docs/Mozilla/Add-ons/SDK/High-Level_APIs/simple-prefs">simple-prefs</a> API 来存储首选项,WebExtension 版本不可能访问这项数据。</p>
+
+<p>使用嵌入式 WebExtensions,您可以创建一个嵌入了 WebExtension 的附加组件中间版本来迁移数据。中间版本使用旧式 API 读取存储的数据,然后使用 WebExtension API 写入数据。</p>
+
+<ul>
+ <li>在初始版本中,基于 SDK 的附加组件使用 <a href="/en-US/docs/Mozilla/Add-ons/SDK/High-Level_APIs/simple-prefs">simple-prefs</a> API 读取和写入附加组件首选项。</li>
+ <li>
+ <p>在中间版本中,SDK 附加组件启动嵌入式 WebExtension。WebExtension 要求 SDK 附加组件用 simple-prefs 检索存储的数据。WebExtension 然后使用 {{WebExtAPIRef("storage")}} API 存储数据。</p>
+
+ <div class="note">
+ <p>在某些情况下,中间版本必须在初始导入后保持数据同步。例如,<a href="/en-US/Add-ons/WebExtensions/Embedded_WebExtensions#Add-on_preferences_UI">附加组件的首选项界面仍然使用旧系统</a>,所以如果用户在这里修改了设置,它修改的是旧数据。中间的附加组件必须监听这些更改并将新数据发送到嵌入式 WebExtension。</p>
+
+ <p>有个 <a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-sdk">"embedded-webextension-sdk"</a> 示例说明了这一点。</p>
+ </div>
+ </li>
+ <li>在最终版本中,附加组件只是一个 WebExtension,并且只使用存储 API。</li>
+</ul>
+
+<p>我们提供了两个例子说明此模式:<a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-bootstrapped">"embedded-webextension-bootstrapped"</a> 展示了从一个自举式附加组件迁移,而 <a href="https://github.com/mdn/webextensions-examples/tree/master/embedded-webextension-sdk">"embedded-webextension-sdk"</a> 展示了从一个 SDK 附加组件迁移。</p>
+
+<h2 id="限制">限制</h2>
+
+<h3 id="调试">调试</h3>
+
+<p>如果您有一个嵌入了 WebExtension 的旧式附加组件,您不能使用新的附加组件调试器来调试它。您必须使用基于浏览器工具箱的<a href="/en-US/Add-ons/WebExtensions/Debugging_(before_Firefox_50)">旧版调试工具</a>。</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/examples/index.html b/files/zh-cn/mozilla/add-ons/webextensions/examples/index.html
new file mode 100644
index 0000000000..ce413198ea
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/examples/index.html
@@ -0,0 +1,31 @@
+---
+title: 扩展示例
+slug: Mozilla/Add-ons/WebExtensions/Examples
+tags:
+ - firefox extension
+ - firefox 扩展
+ - 扩展案例
+ - 火狐扩展
+translation_of: Mozilla/Add-ons/WebExtensions/Examples
+---
+<div>{{AddonSidebar}}</div>
+
+<p>为帮助了解如何开发扩展,我们维护了一个包含简单扩展示例的代码仓库在<a href="https://github.com/mdn/webextensions-examples">https://github.com/mdn/webextensions-examples</a>. 本文描述了仓库代码中所使用的 WebExtension APIs。</p>
+
+<p>这些示例工作在 Firefox Nightly 下: 大部分示例在 Firefox 的早期版本中也能够运行, 请检查扩展 manifest.json 文件中的 <a href="/en-US/Add-ons/WebExtensions/manifest.json/applications">strict_min_version</a> 键。</p>
+
+<p>如果你想尝试这些示例,有下面三个选择:</p>
+
+<ol>
+ <li>克隆代码库,通过 <a href="/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">"临时载入附加组件"</a> 功能直接从源文件夹中载入扩展组件。再重启浏览器前该扩展将一直存在。</li>
+ <li>克隆代码库,使用 <a href="/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext">web-ext</a> 命令行工具运行安装了扩展的 Firefox。</li>
+ <li>克隆代码库,进入 <a href="https://github.com/mdn/webextensions-examples/tree/master/build">build</a> 文件夹。该文件夹包含所有示例的已构建、带签名版本。你可以在Firefox中打开(菜单栏-&gt;文件-&gt;打开文件)并且永久安装这些扩展。这些扩展和直接从 <a href="https://addons.mozilla.org/en-US/firefox/">addons.mozilla.org</a> 安装的扩展别无二致。</li>
+</ol>
+
+<div class="blockIndicator warning">
+<p><strong>重要</strong>:不要提交这些关于 WebExtension 例子的示例到 AMO (addons.mozilla.org)  上去,你无需为附加组件签名就能运行 WebExtension 的示例。只要按照上面的步骤来就可以了。</p>
+</div>
+
+<p>如果你想对代码仓库贡献,<a href="https://github.com/mdn/webextensions-examples/blob/master/CONTRIBUTING.md">给我们发送 pull request!</a></p>
+
+<p>{{WebExtAllExamples}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/extending_the_developer_tools/index.html b/files/zh-cn/mozilla/add-ons/webextensions/extending_the_developer_tools/index.html
new file mode 100644
index 0000000000..cf44f0de27
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/extending_the_developer_tools/index.html
@@ -0,0 +1,164 @@
+---
+title: 扩展开发人员工具
+slug: Mozilla/Add-ons/WebExtensions/Extending_the_developer_tools
+tags:
+ - Add-ons
+ - DevTools
+ - Guide
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/Extending_the_developer_tools
+---
+<div>{{AddonSidebar}}</div>
+
+<div class="note">
+<p>本页介绍了火狐 Firefox 55中存在的开发工具接口(dectools APIs)。 虽然该接口Api基于 Chrome 开发工具Api,仍有许多功能尚未实现在火狐中实现,因此未记录在本页内容中。产看当前缺失的功能,请参阅链接<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Using_the_devtools_APIs#Limitations_of_the_devtools_APIs">开发工具Api的限制.</a></p>
+</div>
+
+<p>您可以使用WebExtensions API扩展浏览器的内置开发人员工具。要创建devtools扩展,请在manifest.json中包含“ devtools_page”键:</p>
+
+<pre class="brush: json notranslate">"devtools_page": "devtools/devtools-page.html"</pre>
+
+<p>此项的值是指向与您的扩展程序捆绑在一起的HTML文件的URL。该URL应相对于manifest.json文件本身。</p>
+
+<p>HTML文件在扩展中定义了一个特殊页面,称为devtools页面。</p>
+
+<h2 id="devtools页面">devtools页面</h2>
+
+<p>当打开浏览器devtools时,将加载devtools页面,并在关闭浏览器时将其卸载。请注意,由于devtools窗口与单个选项卡相关联,因此很可能同时存在多个devtools窗口-因此有多个devtools页面。</p>
+
+<p>devtools页面没有任何可见的DOM,但可以包含使用&lt;script&gt;标记的JavaScript源。源必须与扩展本身捆绑在一起。来源可以访问::</p>
+
+<ul>
+ <li>可通过全局窗口对象访问的普通DOM API</li>
+ <li>与内容脚本中相同的WebExtension API</li>
+ <li>The devtools APIs:
+ <ul>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.inspectedWindow">devtools.inspectedWindow</a></code></li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.network">devtools.network</a></code></li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.panels">devtools.panels</a></code></li>
+ </ul>
+ </li>
+</ul>
+
+<p>请注意,devtools页面无法访问任何其他WebExtension API,并且后台页面无法访问devtools API。相反,devtools页面和后台页面必须使用运行时消息传递API进行通信。这是一个例子:</p>
+
+<pre class="brush: html notranslate">&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+  &lt;head&gt;
+    &lt;meta charset="utf-8"&gt;
+  &lt;/head&gt;
+  &lt;body&gt;
+    &lt;script src="devtools.js"&gt;&lt;/script&gt;
+  &lt;/body&gt;
+&lt;/html&gt;</pre>
+
+<p>devtools.js文件将保存创建您的dev工具扩展的实际代码。</p>
+
+<h2 id="创建面板">创建面板</h2>
+
+<p>devtools窗口中包含许多单独的工具-JavaScript调试器,网络监视器等。顶部的一排标签可让用户在不同的工具之间切换。承载每个工具的用户界面的窗口称为“面板”</p>
+
+<p>使用devtools.panels.create()API,可以在devtools窗口中创建自己的面板:</p>
+
+<pre class="brush: js notranslate">browser.devtools.panels.create(
+ "My Panel", // title
+ "icons/star.png", // icon
+ "devtools/panel/panel.html" // content
+).then((newPanel) =&gt; {
+ newPanel.onShown.addListener(initialisePanel);
+ newPanel.onHidden.addListener(unInitialisePanel);
+});</pre>
+
+<p>这需要三个必选参数:面板的标题,图标和内容。它返回一个Promise,该Promise解析为代表新面板的devtools.panels.ExtensionPanel对象。</p>
+
+<h2 id="与目标窗口互动">与目标窗口互动</h2>
+
+<p>开发人员工具始终附加到特定的浏览器选项卡。这称为开发人员工具的“目标”或“检查的窗口”。您可以使用devtools.inspectedWindow API与检查的窗口进行交互。</p>
+
+<h3 id="Running_code_in_the_target_window">Running code in the target window</h3>
+
+<p>devtools.inspectedWindow.eval()提供了一种在检查的窗口中运行代码的方法。</p>
+
+<p>这有点像使用{{WebExtAPIRef("tabs.executeScript()")}}注入内容脚本,但有一个重要区别:</p>
+
+<ul>
+ <li>与内容脚本不同,使用devtools.inspectedWindow.eval()加载的脚本不会获得“ DOM的清晰视图”:也就是说,它们可以看到页面脚本对页面所做的更改。</li>
+</ul>
+
+<div class="note">
+<p>请注意,DOM的清晰视图是一项安全功能,旨在通过重新定义本机DOM功能的行为来帮助防止恶意页面欺骗扩展。这意味着您需要非常小心地使用eval(),并应尽可能使用普通的内容脚本。</p>
+</div>
+
+<p>devtools.inspectedWindow.eval()加载的脚本也看不到内容脚本定义的任何JavaScript变量。</p>
+
+<h3 id="Working_with_content_scripts">Working with content scripts</h3>
+
+<p>devtools文档无法直接访问{{WebExtAPIRef("tabs.executeScript()")}},因此,如果需要注入内容脚本,devtools文档必须向后台脚本发送一条消息,要求其注入剧本。 devtools.inspectedWindow.tabId提供目标选项卡的ID:devtools文档可以将其传递给后台脚本,而后台脚本又可以将其传递给{{WebExtAPIRef("tabs.executeScript()")}}:</p>
+
+<pre class="brush: js notranslate">// devtools-panel.js
+
+const scriptToAttach = "document.body.innerHTML = 'Hi from the devtools';";
+
+window.addEventListener("click", () =&gt; {
+ browser.runtime.sendMessage({
+ tabId: browser.devtools.inspectedWindow.tabId,
+ script: scriptToAttach
+ });
+});</pre>
+
+<pre class="brush: js notranslate">// background.js
+
+function handleMessage(request, sender, sendResponse) {
+ browser.tabs.executeScript(request.tabId, {
+ code: request.script
+ });
+}
+
+browser.runtime.onMessage.addListener(handleMessage);</pre>
+
+<p>如果您需要在目标窗口中运行的内容脚本和devtools文档之间交换消息,则最好使用{{WebExtAPIRef("runtime.connect()")}}和{{WebExtAPIRef("runtime.onConnect()")}},以在后台页面和devtools文档之间建立连接。然后,后台页面可以维护选项卡ID和{{WebExtAPIRef("runtime.Port")}}对象之间的映射,并使用此映射在两个作用域之间路由消息。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/14923/devtools-content-scripts.png" style="display: block; height: 416px; margin-left: auto; margin-right: auto; width: 600px;"></p>
+
+<h2 id="devtools_API的局限性">devtools API的局限性</h2>
+
+<p>这些API基于Chrome devtools API,但与Chrome相比,许多功能仍缺失。本节列出了从Firefox 54开始尚未实现的功能。请注意,devtools API正在积极开发中,我们希望在将来的版本中增加对其中大多数功能的支持。</p>
+
+<h3 id="devtools.inspectedWindow">devtools.inspectedWindow</h3>
+
+<p>The following are not supported:</p>
+
+<ul>
+ <li><code>inspectedWindow.getResources()</code></li>
+ <li><code>inspectedWindow.onResourceAdded</code></li>
+ <li><code>inspectedWindow.onResourceContentCommitted</code></li>
+</ul>
+
+<p>None of the options to <code>inspectedWindow.eval()</code> are supported.</p>
+
+<p>使用inspectedWindow.eval()注入的脚本不能使用控制台的所有命令行帮助器功能,但是都支持$ 0和inspect(...)(从Firefox 55开始)。</p>
+
+<h3 id="devtools.panels">devtools.panels</h3>
+
+<p>The following are not supported:</p>
+
+<ul>
+ <li><code>panels.elements</code></li>
+ <li><code>panels.sources</code></li>
+ <li><code>panels.setOpenResourceHandler()</code></li>
+ <li><code>panels.openResource()</code></li>
+ <li><code>panels.ExtensionPanel.createStatusBarButton()</code></li>
+ <li><code>panels.Button</code></li>
+ <li><code>panels.ElementsPanel</code></li>
+ <li><code>panels.SourcesPanel</code></li>
+</ul>
+
+<h2 id="Examples">Examples</h2>
+
+<p>The <a href="https://github.com/mdn/webextensions-examples">webextensions-examples</a> repo on GitHub, contains several examples of extensions that use devtools panels:</p>
+
+<ul>
+ <li>
+ <p><a href="https://github.com/mdn/webextensions-examples/blob/master/devtools-panels/">devtools-panels</a> use devtools panels:</p>
+ </li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/index.html b/files/zh-cn/mozilla/add-ons/webextensions/index.html
new file mode 100644
index 0000000000..cdd473ca78
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/index.html
@@ -0,0 +1,122 @@
+---
+title: 浏览器扩展
+slug: Mozilla/Add-ons/WebExtensions
+tags:
+ - WebExtension
+ - WebExtensions
+ - firefox add-on
+ - firefox extensions
+ - web-extensions
+ - 发布
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions
+---
+<div>{{AddonSidebar}}</div>
+
+<p>Extensions「扩展」 可以扩展和修改一个浏览器的能力。用于 Firefox 的 扩展使用 WebExtensions API 「一种开发扩展的跨浏览器系统」构建。该系统与 Google Chrome、Opera 和 <a href="https://browserext.github.io/browserext/">W3C 草案社区组织</a> 所支持的 <a href="https://developer.chrome.com/extensions">扩展 API </a>在很大程度上兼容。大多数情况下为这些浏览器编写的扩展<a href="/zh-CN/Add-ons/WebExtensions/Porting_from_Google_Chrome">只需少许修改</a>即可在 Firefox 或 <a href="https://developer.microsoft.com/zh-CN/microsoft-edge/platform/documentation/extensions/">Microsoft Edge</a> 中运行。这种 API 与也完全兼容 <a href="/zh-CN/Firefox/Multiprocess_Firefox">多进程 Firefox</a>。</p>
+
+<p>如果你有想法或问题,或者在使用 WebExtensions APIs 迁移旧式附加组件时需要帮助,可以在 <a href="https://mail.mozilla.org/listinfo/dev-addons">dev-addons 邮件列表</a> 或者 <a href="https://wiki.mozilla.org/IRC">IRC</a> 上的 <a href="irc://irc.mozilla.org/extdev">#extdev</a> 与我们联系。</p>
+
+<div class="row topicpage-table">
+<div class="section">
+<h2 id="新手入门">新手入门</h2>
+
+<ul>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/What_are_WebExtensions">什么是扩展?</a></li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Your_first_WebExtension">你的第一个扩展</a></li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Your_second_WebExtension">你的第二个扩展</a></li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension">扩展解析</a></li>
+ <li>火狐工作流概述</li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Examples">扩展示例</a></li>
+ <li>下一步</li>
+</ul>
+
+<h2 id="操作方法">操作方法</h2>
+
+<ul>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Intercept_HTTP_requests">拦截 HTTP 请求</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Modify_a_web_page">修改网页</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Add_a_button_to_the_toolbar">在工具栏添加按钮</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Implement_a_settings_page">制作一个设置页面</a></li>
+ <li><a href="/zh-CN//docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard">与剪贴板交互</a></li>
+ <li>使用页签API</li>
+ <li>使用书签API</li>
+</ul>
+
+<h2 id="用户界面">用户界面</h2>
+
+<ul>
+ <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface">简介</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Browser_action">浏览器工具栏按钮</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Page_actions">有弹出面板的浏览器工具栏按钮</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Page_actions">地址栏按钮</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Popups">有弹出面板的地址栏按钮</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Context_menu_items">上下文菜单项</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Sidebars">侧边栏</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Options_pages">选项页面</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Bundled_web_pages">捆绑网页(Bundled web pages)</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Notifications">通知</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Omnibox">地址栏建议</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/devtools_panels">开发者工具面板</a></li>
+</ul>
+
+<h2 id="相关概念">相关概念</h2>
+
+<ul>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Using_the_JavaScript_APIs">使用 JavaScript API</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/User_interface_components">用户界面元素</a></li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Content_scripts">内容脚本</a></li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Match_patterns">模式匹配</a></li>
+ <li><a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Working_with_files">处理文件</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Internationalization">国际化</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy">内容安全政策</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Native_messaging">本地消息</a></li>
+ <li><a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/User_experience_best_practices">用户体验的最佳实践</a></li>
+</ul>
+
+<h2 id="扩展移植">扩展移植</h2>
+
+<ul>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Porting_from_Google_Chrome">移植 Google Chrome 扩展</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Porting_a_legacy_Firefox_add-on">移植传统的 Firefox 附加组件</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Embedded_WebExtensions">嵌入式 WebExtensions</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Comparison_with_the_Add-on_SDK">与 Firefox Add-on SDK 的差异</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Comparison_with_XUL_XPCOM_extensions">与 XUL/XPCOM 的差异</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities">与 Chrome 不兼容的地方</a></li>
+</ul>
+
+<h2 id="Firefox_工作流">Firefox 工作流</h2>
+
+<ul>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">安装</a></li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Debugging">调试</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Getting_started_with_web-ext">开始使用 web-ext</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/web-ext_command_reference">web-ext 命令参考</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID">WebExtensions 与附加组件 ID</a></li>
+ <li><a href="https://developer.mozilla.org/zh-CN/Add-ons/WebExtensions/Alternative_distribution_options">其他分发选项</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Publishing_your_WebExtension">发布你的 WebExtension</a></li>
+</ul>
+</div>
+
+<div class="section">
+<h2 id="参考资料">参考资料</h2>
+
+<h3 id="JavaScript_APIs">JavaScript APIs</h3>
+
+<ul>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/API">JavaScript API概况</a></li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs">JavaScript API 浏览器兼容性表格</a></li>
+</ul>
+
+<div class="twocolumns">{{ ListSubpages ("/zh-CN/Add-ons/WebExtensions/API") }}</div>
+
+<h3 id="Manifest_关键信息">Manifest 关键信息</h3>
+
+<ul>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json 概览</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Browser_compatibility_for_manifest.json">manifest.json 的浏览器兼容性</a></li>
+</ul>
+
+<div class="twocolumns">{{ ListSubpages ("/zh-CN/Add-ons/WebExtensions/manifest.json") }}</div>
+</div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/interact_with_the_clipboard/index.html b/files/zh-cn/mozilla/add-ons/webextensions/interact_with_the_clipboard/index.html
new file mode 100644
index 0000000000..092125a9ca
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/interact_with_the_clipboard/index.html
@@ -0,0 +1,157 @@
+---
+title: Interact with the clipboard
+slug: Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard
+translation_of: Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard
+---
+<div>{{AddonSidebar}}</div>
+
+<p>有两种方式可以让浏览器扩展与系统剪贴板交互: {{domxref("Document.execCommand()")}} 方法以及现代的异步的 <a href="/en-US/docs/Web/API/Clipboard_API">Clipboard API</a>.</p>
+
+<p>{{domxref("Document.execCommand()")}} 方法常通过以下指令使用:</p>
+
+<ul>
+ <li><code>document.execCommand("copy")</code></li>
+ <li><code>document.execCommand("cut")</code></li>
+ <li><code>document.execCommand("paste")</code></li>
+</ul>
+
+<p>Clipboard API 提供了异步的连接来直接读写剪贴板内容. 例, 如此从剪贴板读取文本:</p>
+
+<pre class="brush: js">navigator.clipboard.readText().then(text =&gt; outputElem.innerText = text);</pre>
+
+<p>这将请求剪贴板内容, 并且当接收到响应时存储剪贴板文本到一个元素的 {{domxref("Node.innerText", "innerText")}}.</p>
+
+<div class="blockIndicator note">
+<p>注意: 异步的 Clipboard API 方法是一个近期新增的规范, 并且这个规范可能不适用于所有浏览器. 请在使用前测试了每一种方法的兼容性, 以确保支持满足您的需求.</p>
+</div>
+
+<h2 id="写入系统粘贴板">写入系统粘贴板</h2>
+
+<p>有两种向剪贴板写入数据的方法. 你可以使用 {{domxref("Document.execCommand", "document.execCommand()")}}  来触发 "剪切" 和 "复制" 行为, 这将用选择的数据覆盖剪贴板的当前内容. 另一个选项是使用 Clipboard API 的 {{domxref("Clipboard.writeText()")}} 或 {{domxref("Clipboard.write()")}} 方法来用指定数据覆盖剪贴板内容.</p>
+
+<h3 id="使用_execCommand()">使用 execCommand()</h3>
+
+<p>{{domxref("Document.execCommand", "document.execCommand()")}}  方法的 <code>"cut"</code> 与 <code>"copy"</code> 命令可以被用于以选中素材代替剪贴板的当前内容. 这些命令无需任何特别的权限就可以使用, 如果你在一个用于用户操作的短生存期的事件处理程序中使用他们(例如, 一次点击事件).</p>
+
+<p>例如,假设你有一个下面的弹出菜单页面:</p>
+
+<pre class="brush: html">&lt;input id="input" type="text"/&gt;
+&lt;button id="copy"&gt;Copy&lt;/button&gt;
+</pre>
+
+<p>使 "copy"按钮能复制 "input"中的文本,代码如下:</p>
+
+<pre class="brush: js">function copy() {
+ var copyText = document.querySelector("#input");
+ copyText.select();
+ document.execCommand("Copy");
+}
+
+document.querySelector("#copy").addEventListener("click", copy);</pre>
+
+<p>由于<code>execCommand()</code>命令在单击事件中,所以不需要特别的权限。</p>
+
+<p>此外,如果用警报(alarm)替换上面的命令来触发复制事件:</p>
+
+<pre class="brush: js">function copy() {
+ var copyText = document.querySelector("#input");
+ copyText.select();
+ document.execCommand("Copy");
+}
+
+browser.alarms.create({
+ delayInMinutes: 0.1
+});
+
+browser.alarms.onAlarm.addListener(copy);</pre>
+
+<p>这种触发不一定成功,它取决于浏览器是否支持。Firefox浏览器就不支持该功能,你会在浏览器控制台中看到以下信息:</p>
+
+<pre>"document.execCommand(‘cut’/‘copy’) was denied because it was not called from inside a short running user-generated event handler."</pre>
+
+<p>为了能够在这种情形下使用,你需要拥有"clipboardWrite"的权限( <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a>)。 因此,"clipboardWrite"权限能使你不通过临时事件处理程序就可以写入系统粘贴板中。</p>
+
+<h3 id="使用_Clipboard_API">使用 Clipboard API</h3>
+
+<p>Clipboard API 更加灵活, 因为你不仅可以将当前选择复制到剪贴板中, 还可以直接指定要放入剪贴板的信息.</p>
+
+<p>要使用 Clipboard API 需要在你的 <code>manifest.json</code> 文件中申请 <code>clipboardRead</code> 与 <code>clipboardWrite</code> 权限.</p>
+
+<p>对于页面脚本, 需要权限 API 的 <code>clipboard-write</code> 权限. 你可通过 {{domxref("Permissions.query", "navigator.permissions.query()")}} 来检查这个权限:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js">navigator<span class="punctuation token">.</span>permissions<span class="punctuation token">.</span><span class="function token">query</span><span class="punctuation token">(</span><span class="punctuation token">{</span>name<span class="punctuation token">:</span> <span class="string token">"clipboard-write"</span><span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">.</span><span class="function token">then</span><span class="punctuation token">(</span>result <span class="operator token">=&gt;</span> <span class="punctuation token">{</span>
+ <span class="keyword token">if</span> <span class="punctuation token">(</span>result<span class="punctuation token">.</span>state <span class="operator token">==</span> <span class="string token">"granted"</span> <span class="operator token">||</span> result<span class="punctuation token">.</span>state <span class="operator token">==</span> <span class="string token">"prompt"</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ <span class="comment token">/* write to the clipboard now */</span>
+ <span class="punctuation token">}</span>
+<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>这个函数使用一个字符串作为输入并且用它更新剪贴板:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">function</span> <span class="function token">updateClipboard</span><span class="punctuation token">(</span>newClip<span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ navigator<span class="punctuation token">.</span>clipboard<span class="punctuation token">.</span><span class="function token">writeText</span><span class="punctuation token">(</span>newClip<span class="punctuation token">)</span><span class="punctuation token">.</span><span class="function token">then</span><span class="punctuation token">(</span><span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ <span class="comment token">/* clipboard successfully set */</span>
+ <span class="punctuation token">}</span><span class="punctuation token">,</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ <span class="comment token">/* clipboard write failed */</span>
+ <span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}</span></code></pre>
+
+<h3 id="特定浏览器注意事项">特定浏览器注意事项</h3>
+
+<p> 这里涉及的剪贴板和其他API正在快速发展, 因此浏览器在工作方式上存在差异.</p>
+
+<p>在Chrome中:</p>
+
+<ul>
+ <li>你可以在所有执行上下文中写入系统粘贴板,像背景网页、内容脚本、标签页和弹出菜单。</li>
+ <li>你不需要 <code>"clipboardWrite"</code> 权限,甚至不需要在用户生成的事件处理程序中写入粘贴板</li>
+</ul>
+
+<p>在Firefox中:</p>
+
+<ul>
+ <li>除了背景网页外,你可以在所有执行上下文中使用 execCommand 写入粘贴板。在Firefox中,你无法选择文本或将输入字段聚焦在后台页面中,因此无法使用 execCommand 从后台页面写入剪贴板。</li>
+ <li>只有version 51以上才支持"clipboardWrite" 权限。</li>
+ <li>从 version 57 开始,可以使用 <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/clipboard/setImageData">clipboard.setImageData()</a></code> API 将图像复制到剪贴板。</li>
+ <li>在 Firefox 633 中添加了对 Clipboard API {{domxref("Clipboard.writeText", "navigator.clipboard.writeText()")}} 方法的支持。</li>
+ <li>当使用一个内容脚本,Clipboard API 只可用于 HTTPS 页。解决方法是,在内容脚本和后台脚本之间使用消息传递。</li>
+</ul>
+
+<h2 id="读取系统粘贴板">读取系统粘贴板</h2>
+
+<p><code>execCommand()</code> 方法提供了 <code>"paste"</code> 指令,能让你粘贴内容。你可以使用 Clipboard API 的更灵活的方法: {{domxref("Clipboard.read()")}} 和 {{domxref("Clipboard.readText()")}}。</p>
+
+<h3 id="使用_execCommand()_2">使用 execCommand()</h3>
+
+<p>首先,你需要为扩展申请 <code>"clipboardRead"</code> <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a> 。即便你在用户生成的事件处理程序 ( 例如 {{event("click")}} 或 {{event("keypress")}} ) 中使用 "paste" 指令也是如此。</p>
+
+<p>假设你的HTML页面内容如下:</p>
+
+<pre class="brush: html">&lt;input id="output" type="text"/&gt;
+&lt;button id="paste"&gt;粘贴&lt;/button&gt;
+</pre>
+
+<p>要在用户单机 id 为 <code>"paste"</code> 的 {{HTMLElement("button")}} 时从剪贴板设置 id 为 <code>"output"</code> 的 {{HTMLElement("textarea")}} 的内容,可以使用这样的代码:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">function</span> <span class="function token">paste</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
+ <span class="keyword token">var</span> pasteText <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">querySelector</span><span class="punctuation token">(</span><span class="string token">"#output"</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+ pasteText<span class="punctuation token">.</span><span class="function token">focus</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+ document<span class="punctuation token">.</span><span class="function token">execCommand</span><span class="punctuation token">(</span><span class="string token">"paste"</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>pasteText<span class="punctuation token">.</span>textContent<span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}</span>
+
+document<span class="punctuation token">.</span><span class="function token">querySelector</span><span class="punctuation token">(</span><span class="string token">"#paste"</span><span class="punctuation token">)</span><span class="punctuation token">.</span><span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">"click"</span><span class="punctuation token">,</span> paste<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<h3 id="使用_Clipboard_API_2">使用 Clipboard API</h3>
+
+<p>剪贴板 API 的 {{domxref("Clipboard.readText", "navigator.clipboard.readText()")}} 和 {{domxref("Clipboard.read", "navigator.clipboard.read()")}} 方法让你从剪贴板读取任意文本或二进制数据。这让你从剪贴板访问数据无需将它们粘贴至一个可编辑的元素中。</p>
+
+<p>一旦你通过 <a href="https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API">Permissions API</a> 获取了 <code>"clipboard-read"</code> 权限,你就可以轻松读取剪贴板:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js">navigator<span class="punctuation token">.</span>clipboard<span class="punctuation token">.</span><span class="function token">readText</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">.</span><span class="function token">then</span><span class="punctuation token">(</span>clipText <span class="operator token">=&gt;</span>
+ document<span class="punctuation token">.</span><span class="function token">getElementById</span><span class="punctuation token">(</span><span class="string token">"outbox"</span><span class="punctuation token">)</span><span class="punctuation token">.</span>innerText <span class="operator token">=</span> clipText<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>这个代码片段从剪贴板提取文本并且用该文本替换 ID 为 <code>"outbox"</code> 的元素的当前内容。</p>
+
+<h3 id="特定浏览器注意事项_2">特定浏览器注意事项</h3>
+
+<p>Firefox 在 54 版本提供了 <code>"clipboardRead"</code> <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permission</a> ,但是仅支持向处于 <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Editable_content">内容可编辑模式</a> 的元素粘贴,对于内容脚本,只能在 {{HTMLElement("textarea")}} 工作。对于后台脚本,任何元素都可被设置为内容可编辑模式。</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/intercept_http_requests/index.html b/files/zh-cn/mozilla/add-ons/webextensions/intercept_http_requests/index.html
new file mode 100644
index 0000000000..1e1c155db3
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/intercept_http_requests/index.html
@@ -0,0 +1,158 @@
+---
+title: 拦截HTTP请求
+slug: Mozilla/Add-ons/WebExtensions/Intercept_HTTP_requests
+tags:
+ - Add-ons
+ - Extensions
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/Intercept_HTTP_requests
+---
+<div>{{AddonSidebar}}</div>
+
+<p>使用 {{WebExtAPIRef("webRequest")}} API可以拦截HTTP请求。该API允许开发者植入一个侦听器用以侦听各个阶段的HTTP请求。在侦听器中,你能:</p>
+
+<ul>
+ <li>获取请求及其返回的header和body</li>
+ <li>取消或重定向请求</li>
+ <li>修改请求及其返回的header</li>
+</ul>
+
+<p>本文将探究<code>webRequest</code>模型的三种用法:</p>
+
+<ul>
+ <li>登陆请求的构造</li>
+ <li>重定向请求</li>
+ <li>修改请求的header</li>
+</ul>
+
+<h2 id="记录请求的_URL">记录请求的 URL</h2>
+
+<p>新建一个名为<code>“</code>requests<code>”</code>的目录,在其中新建一个名为<code>“</code>manifest.json<code>”</code>的文件,文件包含如下 内容 :</p>
+
+<pre class="brush: json">{
+ "description": "Demonstrating webRequests",
+ "manifest_version": 2,
+ "name": "webRequest-demo",
+ "version": "1.0",
+
+ "permissions": [
+ "webRequest",
+ "&lt;all_urls&gt;"
+ ],
+
+ "background": {
+ "scripts": ["background.js"]
+ }
+}</pre>
+
+<p>接着新加一个名为<code>“</code>background.js<code>”</code>的文件,包含如下内容:</p>
+
+<pre class="brush: js">function logURL(requestDetails) {
+ console.log("Loading: " + requestDetails.url);
+}
+
+chrome.webRequest.onBeforeRequest.addListener(
+ logURL,
+ {urls: ["&lt;all_urls&gt;"]}
+);
+
+</pre>
+
+<p>这里我们在请求开始之前用{{WebExtAPIRef("webRequest.onBeforeRequest", "onBeforeRequest")}}调用<code>logURL()</code>函数。<code>logURL()</code><code>函数</code>抓取从事件对象发出的请求中的URL,然后将其打印到浏览器的控制台窗口中。<a href="/en-US/Add-ons/WebExtensions/Match_patterns">参数</a><code>{urls: ["&lt;all_urls&gt;"]}</code>表示拦截发往所有URL的HTTP请求。</p>
+
+<p>测试方法是:<a href="/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">安装该WebExtension</a>, <a href="/en-US/docs/Tools/Browser_Console">打开浏览器的控制台</a>,然后开启某个网页即可。在浏览器控制台中就能见到浏览器请求所有资源的URL:</p>
+
+<p>{{EmbedYouTube("X3rMgkRkB1Q")}}</p>
+
+<h2 id="重定向请求">重定向请求</h2>
+
+<p>现在让我们用<code>webRequest</code>来重定向HTTP请求。首先将manifest.json文件内容替换如下:</p>
+
+<pre class="brush: json">{
+
+ "description": "Demonstrating webRequests",
+ "manifest_version": 2,
+ "name": "webRequest-demo",
+ "version": "1.0",
+
+ "permissions": [
+ "webRequest",
+    "webRequestBlocking",
+    "https://mdn.mozillademos.org"
+ ],
+
+ "background": {
+ "scripts": ["background.js"]
+ }
+
+}</pre>
+
+<p>这里唯一的变化是<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a></code>里 新增了<code>“</code><code>webRequestBlocking</code><code>”</code>项。新增这个权限是为了随时都能修改请求。</p>
+
+<p>下一步替换<code>“</code>background.js<code>”</code>文件内容如下:</p>
+
+<pre class="brush: js">var pattern = "https://mdn.mozillademos.org/*";
+
+function redirect(requestDetails) {
+ console.log("Redirecting: " + requestDetails.url);
+ return {
+ redirectUrl: "https://38.media.tumblr.com/tumblr_ldbj01lZiP1qe0eclo1_500.gif"
+ };
+}
+
+chrome.webRequest.onBeforeRequest.addListener(
+ redirect,
+ {urls:[pattern], types:["image"]},
+ ["blocking"]
+);</pre>
+
+<p>此外在请求构造出来之前我们用{{WebExtAPIRef("webRequest.onBeforeRequest", "onBeforeRequest")}}事件侦听器来实现URL替换。侦听器将会用<code>redirectUrl</code>指定的内容替换原有的URL。</p>
+
+<p>这次我们不拦截所有的请求:<code>{urls:[pattern], types:["image"]}</code>选项告诉浏览器必须同时满足如下两点的请求才会被拦截:(1)在<code>“</code> https://mdn.mozillademos.org/<code>”</code>之下的URL; (2)图片资源。该功能的更多说明参见{{WebExtAPIRef("webRequest.RequestFilter")}}。</p>
+
+<p>刚才我们忽略了<code>“blocking</code><code>”</code>选项。要修改请求<code>就要用到“blocking</code><code>”</code>选项,该选项让侦听器函数阻塞住发往网络请求,浏览器将会等待侦听器返回才会继续处理。阅读{{WebExtAPIRef("webRequest.onBeforeRequest")}}以了解更多有关<code>“blocking</code> <code>”</code>的细节。.</p>
+
+<p>测试时打开MDN上的一个包含诸多图片的页面(如<a href="https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor">https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor</a> ),重新加载<a href="/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox#Reloading_a_temporary_add-on">WebExtension</a>,然后重新加载这个页面:</p>
+
+<p>{{EmbedYouTube("ix5RrXGr0wA")}}</p>
+
+<h2 id="修改请求报头">修改请求报头</h2>
+
+<p>最后我们将使用<code>webRequest</code>修改请求报头。在这个例子中我们将修改 "User-Agent"报头,使得在浏览" http://useragentstring.com/"网站下的网页时可以识别浏览器Opera 12.16。</p>
+
+<p>"manifest.json" 可以与上一个例子相同。</p>
+
+<p>修改"background.js" 如下:</p>
+
+<pre class="brush: js">var targetPage = "http://useragentstring.com/*";
+
+var ua = "Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16";
+
+function rewriteUserAgentHeader(e) {
+ for (var header of e.requestHeaders) {
+ if (header.name.toLowerCase() == "user-agent") {
+ header.value = ua;
+ }
+ }
+ return {requestHeaders: e.requestHeaders};
+}
+
+chrome.webRequest.onBeforeSendHeaders.addListener(
+ rewriteUserAgentHeader,
+ {urls: [targetPage]},
+ ["blocking", "requestHeaders"]
+);</pre>
+
+<p>在请求报头被发送前,我们使用 {{WebExtAPIRef("webRequest.onBeforeSendHeaders", "onBeforeSendHeaders")}} 事件监听器来运行一个函数。</p>
+
+<p>只有在向匹配的URL格式的网页发送请求时,这个监听函数才会运行。 还需注意的是,我们再次使用了<code>"blocking"</code>选项。我们还使用了<code>"requestHeaders"</code>选项,使监听器可以传递我们希望的请求报头数组。了解更多{{WebExtAPIRef("webRequest.onBeforeSendHeaders")}}的信息。</p>
+
+<p>侦听函数在请求报头数组中寻找 "User-Agent" 报头,用<code>ua</code>变量替换它的值,然后返回修改后的报头数组 。现在这个修改后的数组会被发送到服务器。</p>
+
+<p>要测试它,先打开 <a href="http://useragentstring.com/">useragentstring.com</a>网址,检查标识浏览器是否为火狐浏览器 。然后加载附加组件, 刷新网址,再次检查标识浏览器,你会发现火狐浏览器被定义为 Opera了:</p>
+
+<p>{{EmbedYouTube("SrSNS1-FIx0")}}</p>
+
+<h2 id="了解更多">了解更多</h2>
+
+<p>学习你能使用的所有<code>webRequest</code> API,查看 <a href="/en-US/Add-ons/WebExtensions/API/WebRequest">reference documentation</a>。</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/internationalization/index.html b/files/zh-cn/mozilla/add-ons/webextensions/internationalization/index.html
new file mode 100644
index 0000000000..88971977ae
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/internationalization/index.html
@@ -0,0 +1,394 @@
+---
+title: 国际化
+slug: Mozilla/Add-ons/WebExtensions/Internationalization
+translation_of: Mozilla/Add-ons/WebExtensions/Internationalization
+---
+<div>{{AddonSidebar}}</div>
+
+<p><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions">WebExtensions</a> API 有一个相当方便的模块可用于附加组件的国际化(<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n">i18n</a>)。我们将在本文中探讨其功能,并为它的运作方式提供一个实例。WebExtensions 的 i18n 系统类似常见的 i18n 用途 JavaScript 库,例如 <a href="http://i18njs.com/">i18n.js</a>。</p>
+
+<div class="note">
+<p>本文中的 WebExtension 实例 <a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a> 可在 GitHub 上查阅。在您阅读下列章节时,可参照它的代码。</p>
+</div>
+
+<h2 id="剖析一个国际化的_WebExtension">剖析一个国际化的 WebExtension</h2>
+
+<p>一个国际化的 WebExtension 与其他 WebExtension 一样可以包含各类功能,如<a href="/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts">后台脚本</a>、<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">内容脚本</a>等,但它也有些额外的部分,从而允许它适应不同的语言区域。目录树大致如下:</p>
+
+<ul class="directory-tree">
+ <li>webextension-根目录/
+ <ul>
+ <li>_locales
+ <ul>
+ <li>en
+ <ul>
+ <li>messages.json
+ <ul>
+ <li>英语消息(字符串)</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>de
+ <ul>
+ <li>messages.json
+ <ul>
+ <li>德语消息(字符串)</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>等其他语言</li>
+ </ul>
+ </li>
+ <li>manifest.json
+ <ul>
+ <li>含按语言区域而定的元数据</li>
+ </ul>
+ </li>
+ <li>myJavascript.js
+ <ul>
+ <li>含用于检索浏览器语言区域、特定语言环境的消息等的 JavaScript。</li>
+ </ul>
+ </li>
+ <li>myStyles.css
+ <ul>
+ <li>含按语言区域而定的 CSS</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+
+<p>让我们逐项探讨这些新特性,因为下列每个章节都是你在国际化 WebExtension 时所要遵循的步骤。</p>
+
+<h2 id="在__locales_中提供本地化的字符串">在 _locales 中提供本地化的字符串</h2>
+
+<div class="pull-aside">
+<div class="moreinfo">你可以使用<a href="http://r12a.github.io/apps/subtags/">Language subtag lookup page</a>上的查找工具查询语言子标签。请注意,你需要搜索语言的英语名称。</div>
+</div>
+
+<p>每个 i18n 系统都需要你提供想支持的各语言区域的已翻译字符串。 在 WebExtensions 中,这些字符串放在一个名为 <code>_locales</code> 的目录中,<code>_locales</code> 目录则位于扩展的根目录。每个语言区域都有一个名叫 <code>messages.json</code> 的文件,其中包含相应的字符串(在 WebExtension 中称作“消息”),这个文件放在 <code>_locales</code> 的子目录下,子目录以对应语言区域的语言子标签来命名。</p>
+
+<p>注意,如果子标签包含一个基本语言和一个区域变种,那么语言与变种之间通常会以连字号隔开,例如 "en-US"。但作为 <code>_locales</code> 的子目录,<strong>它必须采用下划线来分隔</strong>,如 "en_US"。</p>
+
+<p>因此<a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n/_locales" title="1">在我们这个示例应用</a>中,我们有如下几个目录:"en"(英语)、"de"(德语)、"nl"(荷兰语)以及 "ja"(日语)。每个目录都包含一个 <code>messages.json</code> 文件。</p>
+
+<p>现在我们来看其中一个文件(<a href="https://github.com/mdn/webextensions-examples/blob/master/notify-link-clicks-i18n/_locales/en/messages.json">_locales/en/messages.json</a>)的结构:</p>
+
+<pre class="brush: json">{
+ "extensionName": {
+ "message": "Notify link clicks i18n",
+ "description": "Name of the extension."
+ },
+
+ "extensionDescription": {
+ "message": "Shows a notification when the user clicks on links.",
+ "description": "Description of the extension."
+ },
+
+ "notificationTitle": {
+ "message": "Click notification",
+ "description": "Title of the click notification."
+ },
+
+ "notificationContent": {
+ "message": "You clicked $URL$.",
+ "description": "Tells the user which link they clicked.",
+ "placeholders": {
+      "url" : {
+        "content" : "$1",
+        "example" : "https://developer.mozilla.org"
+      }
+    }
+ }
+}</pre>
+
+<p>这个文件是一个标准的 JSON — 其中每个成员都是一个带有名称的对象,里面包含一个 <code>message</code>(消息)和一个 <code>description</code>(描述)。这些项目都是字符串。<code>$URL$</code> 是一个占位符,在 WebExtension 调用 <code>notificationContent</code> 成员时将被一个子字符串替换。你将在接下来的{{anch("从 JavaScript 检索消息字符串")}}章节中了解如何使用。</p>
+
+<div class="note">
+<p><strong>注意:</strong>你可以在 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n/Locale-Specific_Message_reference">Locale-Specific Message reference</a> 里找到更多有关  <code>messages.json</code> 文件中内容的信息。</p>
+</div>
+
+<h2 id="国际化_manifest.json">国际化 manifest.json</h2>
+
+<p>要国际化你的 manifest.json,有几项任务要完成。</p>
+
+<h3 id="在_manifests_中检索本地化的字符串">在 manifests 中检索本地化的字符串</h3>
+
+<p>你的 <a href="https://github.com/mdn/webextensions-examples/blob/master/notify-link-clicks-i18n/manifest.json">manifest.json</a> 包含显示给用户的字符串,例如附加组件的名称和描述。如果你将这些字符串国际化,并将合适的翻译放到 messages.json 中,则用户将根据当前语言区域看到适当的字符串翻译。</p>
+
+<p>要将这些字符串国际化,按如下格式指定:</p>
+
+<pre class="brush: json">"name": "__MSG_extensionName__",
+"description": "__MSG_extensionDescription__",</pre>
+
+<p>我们在在这里检索到消息字符串依赖于浏览器的语言区域,而不仅仅是一个静态字符串。</p>
+
+<p>要这样调用消息字符串,你需要用的方式为:</p>
+
+<ol>
+ <li>两个下划线,接着是</li>
+ <li>字符串 "MSG",接着是</li>
+ <li>一个下划线,接着是</li>
+ <li>你想调用的在 <code>messages.json</code> 中定义的消息名称,接着是</li>
+ <li>两个下划线</li>
+</ol>
+
+<pre><strong>__MSG_</strong> + <em>messageName</em> + <strong>__</strong></pre>
+
+<h3 id="指定默认语言区域">指定默认语言区域</h3>
+
+<p>你还必须在你的 manifest.json 中指定另一个字段,它就是 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/default_locale">default_locale</a>:</p>
+
+<pre class="brush: json">"default_locale": "en"</pre>
+
+<p>如果扩展没有包含浏览器当前语言区域的本地化字符串,则会使用该字段所指定的默认语言区域。任何浏览器语言区域下不可用的消息字符串都将用默认语言区域的字符串替换。有关浏览器如何选择字符串,还有一些细节需要注意 — 详见{{anch("选择本地化的字符串")}}。</p>
+
+<h2 id="依赖语言区域的_CSS">依赖语言区域的 CSS</h2>
+
+<p>您还可以在扩展的 CSS 文件中检索本地化的字符串。例如,您可能想构建一个依赖于语言区域的 CSS 规则,如下所示:</p>
+
+<pre class="brush: css">header {
+ background-image: url(../images/__MSG_extensionName__/header.png);
+}</pre>
+
+<p>这很有用,不过在这种情况下使用{{anch("预定义消息")}}来处理或许会更好。</p>
+
+<h2 id="从_JavaScript_检索消息字符串">从 JavaScript 检索消息字符串</h2>
+
+<p>所以,您应该已经建立起您的消息字符串和 manifest。现在只需开始从 JavaScript 调用这些消息字符串,以便你的扩展尽可能多地表述适合的语言。实际上 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/i18n">i18n API</a> 相当简单,只需包含以下四个主要的方法(method):</p>
+
+<ul>
+ <li>你最常用的很可能是 {{WebExtAPIRef("i18n.getMessage()")}} — 使用此方法可以检索一个指定的语言字符串。下方有特定的用法示例。</li>
+ <li>{{WebExtAPIRef("i18n.getAcceptLanguages()")}} 和 {{WebExtAPIRef("i18n.getUILanguage()")}} 这两个方法可以在你需要根据语言区域自定义用户界面时使用 — 或许你希望根据用户想要的语言在首选项列表更高层显示首选项,或只显示和特定语言有关的文化信息,又或是按浏览器语言显示格式化过的日期。</li>
+ <li>{{WebExtAPIRef("i18n.detectLanguage()")}} 这个方法可以用来检测用户提交内容的语言,并将其正确格式化。</li>
+</ul>
+
+<p>在我们的 <a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a> 示例中,<a href="https://github.com/mdn/webextensions-examples/blob/master/notify-link-clicks-i18n/background-script.js">后台脚本</a>包含下列代码:</p>
+
+<pre class="brush: js">var title = browser.i18n.getMessage("notificationTitle");
+var content = browser.i18n.getMessage("notificationContent", message.url);</pre>
+
+<p>第一行是从最适合当前语言区域的可用 <code>messages.json</code> 文件中检索 <code>notificationTitle</code> <code>message</code> 字段。第二行与第一行类似,但它被传递了一个 URL 作为第二参数。怎么一回事?它就是你所指定的要替代 <code>notificationContent</code> 消息字段里 <code>$URL$</code> 占位符的内容:</p>
+
+<pre class="brush: json">"notificationContent": {
+ "message": "您点击了 $URL$。",
+ "description": "告诉用户点击了哪个链接。",
+ "placeholders": {
+ "url" : {
+ "content" : "$1",
+ "example" : "https://developer.mozilla.org"
+ }
+ }
+}
+</pre>
+
+<p><code>"placeholders"</code> 这个成员定义了所有的占位符,以及它们所检索的来源。<code>"url"</code> 这个占位符指定了其内容取自 $1,它就是<code> getMessage() 第二个参数里的第一个值。由于占位符就叫做</code> <code>"url",我们就在实际的消息字符串中用</code> <code>$URL$</code> 调用它(<code>"name"</code> 用<code> $NAME$</code> 调用也是一样的,以此类推)。对于多个占位符,你可以将其置于数组内,并作为第二个参数传递到 {{WebExtAPIRef("i18n.getMessage()")}} — <code>[a, b, c]</code> 可替换为 <code>$1</code>, <code>$2</code>, and <code>$3,以此类推,并置于</code> <code>messages.json</code> 内。</p>
+
+<p>接下来我们看一个例子:在 <code>en/messages.json 文件中</code>原始的 <code>notificationContent</code> 消息字符串如下: in the <code>en/messages.json</code> file is</p>
+
+<pre>您点击了 $URL$。</pre>
+
+<p>我们可以看到链接点击后会打开 <code>https://developer.mozilla.org。</code>在 {{WebExtAPIRef("i18n.getMessage()")}} 调用后,第二个参数的内容就变成了 messages.json 里的 <code>$1</code>,并替换定义在 <code>"url" 占位符里的</code> <code>$URL$</code> 这个占位符。所以最后的消息字符串就变成了:</p>
+
+<pre>您点击了 https://developer.mozilla.org。</pre>
+
+<h3 id="直接占位符的使用">直接占位符的使用</h3>
+
+<p>你可以直接将变量<code>($1</code>, <code>$2</code>, <code>$3</code> 等)插入消息字符串,例如我们可以将上述的<code> "notificationContent"</code> 成员重写为:</p>
+
+<pre class="brush: json">"notificationContent": {
+ "message": "你点击了 $1。",
+ "description": "告诉用户点击了哪个链接。"
+}</pre>
+
+<p>这么做看起来似乎更快捷,也没那么复杂,但另一种方法(使用 <code>"placeholders")更切实际,因为提供一个占位符名</code>(例如 <code>"url"</code>)和 example 可帮你记住占位符是什么 — 在你代码写了一个礼拜后,你很可能忘了 <code>$1</code>–<code>$8</code> 表示什么,但你或许记得起来占位符名表示什么。</p>
+
+<h3 id="替换硬编码">替换硬编码</h3>
+
+<p>也可以在占位符中包含硬编码的字符串,从而每次都使用相同的值,而不是从代码中的变量获取值。例如:</p>
+
+<pre class="brush: json">"mdn_banner": {
+ "message": "For more information on web technologies, go to $MDN$.",
+ "description": "Tell the user about MDN",
+ "placeholders": {
+ "mdn": {
+ "content": "https://developer.mozilla.org/"
+ }
+ }
+}</pre>
+
+<p>在本例中我们只是硬编码了占位符的内容,而不是从 <code>$1 这样的变量值中获取它。有时候你会遇到消息文件非常复杂,或者如果你想将文件里的不同值分离开来以便字符串可读性更好,</code>这种情况下它会很有用,这些值可通过编程来访问。</p>
+
+<p>此外,你可使用这样的替代方式指定不想被翻译的一部分字符串,例如人名或公司名。</p>
+
+<h2 id="选择本地化的字符串">选择本地化的字符串</h2>
+
+<p>语言区域可以仅使用语言代码指定,例如 <code>fr</code> 或 <code>en</code>,也可以进一步限定区域代码,例如 <code>en_US</code> 或 <code>en_GB</code>,其描述了使用相同基础语言的区域变体。当您向 i18n 系统询问一个字符串时,它将使用以下算法选择一个字符串:</p>
+
+<ol>
+ <li>如果有精确匹配当前语言区域的 <code>messages.json</code> 文件,并且它包含该字符串,则返回它。</li>
+ <li>否则,如果当前语言区域有合格区域(例如 <code>en_US</code>)并且有一个无区域限定的 <code>messages.json</code> 文件(例如 <code>en</code>)且包含该字符串,则返回它。</li>
+ <li>否则,如果 <code>manifest.json 里包含</code> <code>default_locale</code> 所对应的 <code>messages.json</code> 文件且包含该字符串,则返回它。</li>
+ <li>否则,返回一个空字符串。</li>
+</ol>
+
+<p>参见下列示例:</p>
+
+<ul class="directory-tree">
+ <li>webextension-root-directory/
+ <ul>
+ <li>_locales
+ <ul>
+ <li>en_GB
+ <ul>
+ <li>messages.json
+ <ul>
+ <li><code>{ "colorLocalised": { "message": "colour", "description": "Color." }, ... }</code></li>
+ </ul>
+ </li>
+ </ul>
+ en
+
+ <ul>
+ <li>messages.json
+ <ul>
+ <li><code>{ "colorLocalised": { "message": "color", "description": "Color." }, ... }</code></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ <li>fr
+ <ul>
+ <li>messages.json
+ <ul>
+ <li><code>{ "colorLocalised": { "message": "<span lang="fr">couleur</span>", "description": "Color." }, ...}</code></li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+</ul>
+
+<p>假设 <code>default_locale</code> 是设为 <code>fr</code>,而浏览器的语言环境为 <code>en_GB</code>:</p>
+
+<ul>
+ <li>如果该附加组件调用 <code>getMessage("colorLocalised")</code>,它将返回 "colour"。</li>
+ <li>如果 "colorLocalised" 没有在 <code>en_GB</code> 中提供,那么 <code>getMessage("colorLocalised")</code> 将返回 "color" 而不是 "couleur".</li>
+</ul>
+
+<h2 id="预定义消息">预定义消息</h2>
+
+<p>i18n 模块为我们提供了一些预定义的消息,我们可以用之前在 {{anch("Calling message strings from manifests and extension CSS")}} 中看到的相同的方式调用。例如:</p>
+
+<pre>__MSG_extensionName__</pre>
+
+<p>预定义的消息使用完全相同的语法,例如在消息名称之前使用 <code>@@</code></p>
+
+<pre>__MSG_@@ui_locale__</pre>
+
+<p>下表显示了各个可用的预定义消息。</p>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">消息名</th>
+ <th scope="col">描述</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>@@extension_id</code></td>
+ <td>扩展或应用的 ID;你可以使用该字符串构建 URL,用于扩展内部的资源。甚至未本地化的扩展也可以使用该消息。<br>
+ <strong>注意:</strong>该消息无法在 manifest 文件中使用。</td>
+ </tr>
+ <tr>
+ <td><code>@@ui_locale</code></td>
+ <td>当前的语言区域;你可以使用该字符串构建语言区域特有的 URL。</td>
+ </tr>
+ <tr>
+ <td><code>@@bidi_dir</code></td>
+ <td>当前语言区域对应的文本书写方向,可以是 "ltr",例如英语这样的从左到右书写的语言,或"rtl",例如阿拉伯语这样的从右到左书写的语言。</td>
+ </tr>
+ <tr>
+ <td><code>@@bidi_reversed_dir</code></td>
+ <td>如果 <code>@@bidi_dir</code> 是 "ltr",则是 "rtl",否则是 "ltr"。</td>
+ </tr>
+ <tr>
+ <td><code>@@bidi_start_edge</code></td>
+ <td>如果 <code>@@bidi_dir</code> 是 "ltr",则是 "left",否则是 "right"。</td>
+ </tr>
+ <tr>
+ <td><code>@@bidi_end_edge</code></td>
+ <td>如果<code> @@bidi_dir</code> 是 "ltr",则是 "right",否则是 "left"。</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>回到我们之前的例子,像下面这样写更有意义:</p>
+
+<pre class="brush: css">header {
+ background-image: url(../images/__MSG_@@ui_locale__/header.png);
+}</pre>
+
+<p>现在我们可以保存本地指定的图片,目录则可以根据所支持的不同语言区域进行匹配,例如 en、de 等 — 这样显得更有意义多了。</p>
+
+<p>让我们看看一个在 CSS 文件中使用 <code>@@bidi_*</code> 消息的例子:</p>
+
+<pre class="brush: css">body {
+ direction: __MSG_@@bidi_dir__;
+}
+
+div#header {
+ margin-bottom: 1.05em;
+ overflow: hidden;
+ padding-bottom: 1.5em;
+ padding-__MSG_@@bidi_start_edge__: 0;
+ padding-__MSG_@@bidi_end_edge__: 1.5em;
+ position: relative;
+}</pre>
+
+<p>对于从左到右语言(例如英语、中文),该 CSS 声明调用在上面预定义的消息,最终转换为下列代码:</p>
+
+<pre class="brush: css">direction: ltr;
+padding-left: 0;
+padding-right: 1.5em;
+</pre>
+
+<p>而对于从右到左语言(如阿拉伯语),则将得到:</p>
+
+<pre class="brush: css">direction: rtl;
+padding-right: 0;
+padding-left: 1.5em;</pre>
+
+<h2 id="测试你的_WebExtension">测试你的 WebExtension</h2>
+
+<p>从 Firefox 45 开始,你可以临时安装磁盘上的 WebExtensions  — 另见<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Packaging_and_installation#Loading_from_disk">从磁盘加载。</a>按上述步骤操作,然后尝试我们的 <a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a> WebExtension。访问你喜欢的任何网站,然后点一下链接,查看是否有通知出现来显示所点击的链接网址。</p>
+
+<p>接下来,将 Firefox 的语言区域更改为你想测试的扩展支持的某个语言区域。</p>
+
+<ol>
+ <li>在 Firefox 中打开 "about:config",找到 <code>general.useragent.locale</code> 首选项。</li>
+ <li>双击该首选项(或按回车)以选择它,输入你想测试的语言环境的语言代码,然后点击“确定”(或按回车)。我们的示例扩展支持“en”(英语)、“de”德语()、“nl”(荷兰语)和“ja”日语。</li>
+ <li>重启你的浏览器以完成更改。</li>
+</ol>
+
+<div class="note">
+<p><strong>Note</strong>: 这个方法可以用来修改浏览器的语言区域,即使你未安装过该语言区域对应的<a href="https://addons.mozilla.org/en-US/firefox/language-tools/">语言包</a>。这样的话你就可以将浏览器用户界面调整显示为你的默认语言。</p>
+</div>
+
+<ol>
+</ol>
+
+<p>再次从磁盘临时加载该扩展,然后测试你的新语言区域:</p>
+
+<ul>
+ <li>再次访问 "about:addons" — 你现在应该看到该附加组件已列出其图标,以及相应语言的名称和描述。</li>
+ <li>再次测试你的 WebExtension。在我们的例子中,你会转到另一个网站并点击一个链接,以查看该通知现在是否以相应语言显示。</li>
+</ul>
+
+<p>{{EmbedYouTube("R7--fp5pPGg")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/author/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/author/index.html
new file mode 100644
index 0000000000..a688478298
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/author/index.html
@@ -0,0 +1,40 @@
+---
+title: 作者 - author
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/author
+tags:
+ - 作者
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/author
+---
+<div>{{AddonSidebar}}</div>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">值类型</th>
+ <td><code>字符串(String)</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>非强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"author": "小明"</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>附加组件的作者, 用于在浏览器用户界面上显示, 这样别人下载安装使用该附加组件的时候, 就能看见你的大名了.</p>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json">"author": "小明"</pre>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.author")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/background/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/background/index.html
new file mode 100644
index 0000000000..df4e1fc9ae
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/background/index.html
@@ -0,0 +1,88 @@
+---
+title: 后台 - background
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/background
+tags:
+ - 后台
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/background
+---
+<div>{{AddonSidebar}}</div>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">Type</th>
+ <td><code>Object</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>不强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"background": {
+ "scripts": ["background.js"]
+}</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>通过background 键来给您的扩展程序引入一个或者多个后台脚本文件,以及一个可选的后台页面文件。</p>
+
+<p>后台脚本放置的是需要长期保持状态,或者需要执行长期的操作,并且与任意特定网页或者浏览器窗口的生命周期无关的代码。</p>
+
+<p>后台脚本会在扩展程序被加载后立即被加载,并且一直保持被加载状态,只有在扩展程序被禁止或者卸载的时候才停止运行。只要您获得了必要的许可<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a>,您可以在该脚本中使用任意的扩展程序API。</p>
+
+<p>浏览<a href="/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_pages">Anatomy of a WebExtension</a>中的Background pages部分以获取更多的细节。</p>
+
+<p>background 键最多只能拥有以下的两个属性,两个属性都是可选属性:</p>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td><code>"scripts"</code></td>
+ <td>
+ <p>一个字符串数组,数组中的每个字符串都是JavaScript源文件相对于manifest.json的相对路径,JavaScript源文件便是些被包含在扩展程序中的后台脚本文件。</p>
+
+ <p>脚本共享相同的全局窗口</p>
+
+ <p>脚本按照在数组中的顺序进行加载</p>
+
+ <p><strong>注意在低于Firefox 50版本的浏览器下会出现一个问题:</strong>当Firefox debugger已经打开时,脚本并不能总是按照数组中定义的顺序进行加载。若要解决这个问题,您可以使用page属性,用&lt;script&gt;标签将后台脚本文件从页面中加载进来。这个问题已经在Firefox 50中被修复。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>"page"</code></td>
+ <td>
+ <p>如果您仅仅指定了“scripts”属性,将生成一个空白的页面来运行指定的脚本。</p>
+
+ <p>如果您需要在页面中显示某些特定的内容,您可以使用“page”属性来定义自己的页面。</p>
+
+ <p dir="ltr" id="tw-target-text">如果您使用此属性,您仍然可以使用“script”属性来指定后台脚本,但您也可以就像在普通网页中一样在页面中包含自己的脚本。</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="示例">示例</h2>
+
+<p>加载2个后台脚本文件.</p>
+
+<pre class="brush: json">  "background": {
+    "scripts": ["jquery.js", "my-background.js"]
+  }</pre>
+
+<p>加载1个自定义的后台页面文件.</p>
+
+<pre class="brush: json"> "background": {
+ "page": "my-background.html"
+ }</pre>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.background", 10)}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_action/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_action/index.html
new file mode 100644
index 0000000000..f2e1ff07d1
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_action/index.html
@@ -0,0 +1,209 @@
+---
+title: browser_action
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/browser_action
+tags:
+ - Add-ons
+ - Extensions
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/browser_action
+---
+<div>{{AddonSidebar}}</div>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">类型</th>
+ <td><code>Object</code></td>
+ </tr>
+ <tr>
+ <th scope="row">是否必须</th>
+ <td>否</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json no-line-numbers">
+"browser_action": {
+ "browser_style": true,
+ "default_icon": {
+ "16": "button/geo-16.png",
+ "32": "button/geo-32.png"
+ },
+ "default_title": "Whereami?",
+ "default_popup": "popup/geo.html"
+}</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>浏览器按钮(browser action)指您的扩展在浏览器工具栏上所添加的按钮。该按钮有个图标,并可可选地拥有一个使用 HTML,CSS,和 JavaScript 指定内容的弹出窗口。</p>
+
+<p>如果您使用弹窗(popup),则该弹窗将在用户点击该按钮时打开,并且弹窗中你所提供的运行中的 JavaScript 将可处理用户与其的交互。如果您不使用弹窗,则会在用户点击该按钮时将点击事件传递给你扩展的 <a href="/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts">background scripts</a> 中。</p>
+
+<p>您同样可以使用 <a href="/zh-CN/Add-ons/WebExtensions/API/browserAction">browserAction API</a> 以编程的方式创建及控制浏览器按钮。</p>
+
+<h2 id="语法">语法</h2>
+
+<p><code>browser_action</code> 键是一个可能有以下任何属性的对象,均是可选:</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col">名称</th>
+ <th scope="col">类型</th>
+ <th scope="col">详细描述</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>browser_style</code></td>
+ <td><code>Boolean</code></td>
+ <td>
+ <div class="geckoVersionNote">Firefox 48 中新出现</div>
+
+ <p>可选,默认为 <code>false</code>。</p>
+
+ <p>使用此项来包含一个样式表以使其与浏览器 UI 和其它使用了 <code>browser_style</code> 属性的扩展外观上保持一致。虽然此键值默认为 <code>false</code>,还是建议您将其包含并设其为 <code>true</code>。</p>
+
+ <p>在 Firefox 中,该样式表详阅 chrome://browser/content/extension.css,OS X 系统或见于 chrome://browser/content/extension-mac.css。</p>
+
+ <p><a href="https://firefoxux.github.io/StyleGuide/#/controls">Firefox Style Guide</a> 记述了为获得特定样式您所能为弹窗中元素应用的 class。</p>
+
+ <p><a href="https://github.com/mdn/webextensions-examples/tree/master/latest-download">latest-download</a> 中的示例扩展的弹窗使用了 <code>browser_style</code>。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>default_area</code></td>
+ <td><code>String</code></td>
+ <td>
+ <div class="geckoVersionNote">Firefox 54 中新出现</div>
+
+ <p>定义浏览器最初放置该按钮的位置。该字符串可能是以下四个值中的一个:</p>
+
+ <ul>
+ <li>"navbar":按钮会被放置到浏览器主工具栏中,与 URL 栏并肩。</li>
+ <li>"menupanel":按钮会被放置到弹出面板中。</li>
+ <li>"tabstrip":按钮会被放置到包含浏览器选项卡的工具栏中。</li>
+ <li>"personaltoolbar":按钮会被放置到书签工具栏中。</li>
+ </ul>
+
+ <p>该属性只有 Firefox 支持。</p>
+
+ <p>这个属性是可选的,并默认为 "navbar"。</p>
+
+ <p>扩展不能在其被安装后主动更改其按钮的位置,但用户可以使用浏览器内置的界面定制机制来移动按钮。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>default_icon</code></td>
+ <td><code>Object</code> 或 <code>String</code></td>
+ <td>
+ <p>使用此项以指定一个或多个 browser action 之图标。该图标默认显示在浏览器工具栏里。</p>
+
+ <p>图标使用相对于 manifest.json 文件本身的 URL 指定。</p>
+
+ <p>你可以通过提供一个字符串以指定单个的图标文件:</p>
+
+ <pre class="brush: json no-line-numbers">
+"default_icon": "path/to/geo.svg"</pre>
+
+ <p>要指定多个不同大小的图标,则在此指定一个对象。每个属性的名字是以像素记的该图标的高,且其必须被转换为一个整数。值为其 URL。示例:</p>
+
+ <pre class="brush: json no-line-numbers">
+ "default_icon": {
+ "16": "path/to/geo-16.png",
+ "32": "path/to/geo-32.png"
+ }</pre>
+
+ <p>参阅 <a href="/zh-CN/Add-ons/WebExtensions/manifest.json/browser_action#选择图标大小">选择图标大小</a> 以获得此项的更多指引。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>default_popup</code></td>
+ <td><code>String</code></td>
+ <td>
+ <p>指向包含弹窗信息的 HTML 文件之路径</p>
+
+ <p>该 HTML 文件可能会使用 <code><a href="/zh-CN/docs/Web/HTML/Element/link">&lt;link&gt;</a></code> and <code><a href="/zh-CN/docs/Web/HTML/Element/script">&lt;script&gt;</a></code> 元素来包含 CSS 和 JavaScript,就像普通网页一样。</p>
+
+ <p>与普通网页不同,弹窗中运行的 JavaScript 能访问所有的 <a href="/en-US/Add-ons/WebExtensions/API">WebExtension APIs</a>(当然,仅对于拥有适当<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a>的扩展)。</p>
+
+ <p>这是一个<a href="/zh-CN/Add-ons/WebExtensions/Internationalization#国际化_manifest.json">可本地化属性</a>。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>default_title</code></td>
+ <td><code>String</code></td>
+ <td>
+ <p>按钮的工具提示,在用户将鼠标移到其上时显示。</p>
+
+ <p>这是一个<a href="/zh-CN/Add-ons/WebExtensions/Internationalization#国际化_manifest.json">可本地化属性</a>。</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="选择图标大小">选择图标大小</h2>
+
+<p>浏览器按钮的图标在不同上下文中可能需要以不同大小显示:</p>
+
+<ul>
+ <li>图标默认是在浏览器工具栏中显示,但用户能把它挪到浏览器菜单面板里(那个在用户点击 “汉堡” 图标时打开的面板)。工具栏里的图标比菜单面板里的图标小。</li>
+ <li>在像 Retina 屏的高密度显示器上,图标大要两倍。</li>
+</ul>
+
+<p>如果浏览器在给定的情况下找不到正确尺寸的图标,它就会选最匹配的并对其缩放。缩放可能会使图标模糊,所以一件很重要的事情就是小心地选择图标尺寸。</p>
+
+<p>对此有两种常用方法。你可以以 SVG 文件的形式提供单个图标,然后它就会被正确地缩放:</p>
+
+<pre class="brush: json no-line-numbers">"default_icon": "path/to/geo.svg"</pre>
+
+<p>或者,您可以提供几个不同尺寸的图标,浏览器将选择最佳匹配。</p>
+
+<p>Firefox 中:</p>
+
+<ul>
+ <li>工具栏中图标的默认宽高为 16 * <code><a href="/zh-CN/docs/Web/API/Window/devicePixelRatio">window.devicePixelRatio</a></code>。</li>
+ <li>菜单面板中图标的默认宽高为 32 * <code><a href="/zh-CN/docs/Web/API/Window/devicePixelRatio">window.devicePixelRatio</a></code>。</li>
+</ul>
+
+<p>所以你可以选定精确匹配的图标,不论普通屏还是 Retina 屏的显示,都仅需要提供三个图标文件,并把它们像这样确定下来:</p>
+
+<pre class="brush: json no-line-numbers"> "default_icon": {
+ "16": "path/to/geo-16.png",
+ "32": "path/to/geo-32.png",
+ "64": "path/to/geo-64.png"
+ }</pre>
+
+<p>如果 Firefox 找不到其需要的精确匹配的尺寸,则它会选择大于理想尺寸的已指定的最小图标。如果所有图标都小于理想尺寸,它就将选择已指定的最大图标。</p>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json no-line-numbers">"browser_action": {
+ "default_icon": {
+ "16": "button/geo-16.png",
+ "32": "button/geo-32.png"
+ }
+}</pre>
+
+<p>只有一个图标的浏览器按钮,指定了 2 种不同大小。其扩展的 background scripts 能接收用户点击其图标时的点击事件代码大概像这样:</p>
+
+<pre class="brush: js no-line-numbers"> browser.browserAction.onClicked.addListener(handleClick);</pre>
+
+<pre class="brush: json">"browser_action": {
+ "default_icon": {
+ "16": "button/geo-16.png",
+ "32": "button/geo-32.png"
+ },
+ "default_title": "Whereami?",
+ "default_popup": "popup/geo.html"
+}</pre>
+
+<p>浏览器按钮具有一个图标,一个标题,还有一个弹窗。弹窗会在用户点击按钮时出现。</p>
+
+<p>对于一个简易,但是完整,使用了浏览器按钮的扩展,参见<a href="/zh-CN/Add-ons/WebExtensions/Your_second_WebExtension">演练教程</a>。</p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>{{Compat("webextensions.manifest.browser_action", 10)}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_specific_settings/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_specific_settings/index.html
new file mode 100644
index 0000000000..5d200de3bd
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/browser_specific_settings/index.html
@@ -0,0 +1,66 @@
+---
+title: applications
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings
+tags:
+ - 插件
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings
+---
+<div>{{AddonSidebar}}</div>
+
+<div class="note">
+<p>注意这个key不被Blink-based浏览器(Google Chrome和Opera)支持。如果你在插件中包含了这个key,当在这些浏览器中调用时虽然能用但是会显示警告。</p>
+</div>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">类型</th>
+ <td><code>Object</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>通常不做强制性要求(详细参见<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID#When_do_you_need_an_Add-on_ID">When do you need an Add-on ID</a><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/applications#When_do_I_need_the_applications_key">?</a>)。在Firefox 48版本之前为强制要求。</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"applications": {
+ "gecko": {
+ "id": "addon@example.com",
+ "strict_min_version": "42.0"
+ }
+}</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p><code>applications</code> key包含特定于主机应用程序的键。</p>
+
+<p>目前只包含了一个key:<code>gecko</code>,其中包含了4个attributes:</p>
+
+<ul>
+ <li><code>id</code>即<a href="https://developer.mozilla.org/zh-CN/Add-ons/Install_Manifests#id">extension ID</a>。从Firefox 48起为可选项,在此之前为强制必须项。参看<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID">WebExtensions and the Add-on ID</a>来确认何时需要定义附加组件ID。</li>
+ <li><code>strict_min_version</code>: Gecko所能支持的最小版本号。不允许使用"*"来定义版本号。默认值为 "42a1"。{{gecko_minversion_inline("45")}}</li>
+ <li><code>strict_max_version</code>: Gecko所能支持的最大版本号。如果安装或运行附加组件的Firefox版本号高于这个最大版本号,附加组件将不能运行或不允许被安装。默认值为"*",意思为不对最大版本号做检查。{{gecko_minversion_inline("45")}}</li>
+ <li><code>update_url</code>为链接到<a href="/zh-CN/Add-ons/Updates">add-on update manifest</a>的链接。注意链接必须以"https"开头。这是为了使你自己就能够管理附加组件的更新(如不通过AMO)。{{gecko_minversion_inline("45")}}</li>
+</ul>
+
+<h2 id="Chrome不兼容性">Chrome不兼容性</h2>
+
+<p>你不能在Chrome附加组件中使用这个key。</p>
+
+<h2 id="示例">示例</h2>
+
+<p>示例中包含了所有可能的key。注意你通常不会包含<code>strict_max_version</code>或<code>update_url</code>key在大部分附加组件中。</p>
+
+<pre class="brush: json">"applications": {
+ "gecko": {
+ "id": "addon@example.com",
+ "strict_min_version": "42.0",
+    "strict_max_version": "50.*",
+ "update_url": "https://example.com/updates.json"
+ }
+}</pre>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/content_scripts/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/content_scripts/index.html
new file mode 100644
index 0000000000..9fab86d4b9
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/content_scripts/index.html
@@ -0,0 +1,216 @@
+---
+title: content_scripts
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts
+tags:
+ - WebExtensions
+ - 扩展
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts
+---
+<p>{{AddonSidebar}}</p>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">类型</th>
+ <td>数组(<code>Array)</code></td>
+ </tr>
+ <tr>
+ <th scope="row">必要</th>
+ <td>否</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"content_scripts": [
+ {
+ "matches": ["*://*.mozilla.org/*"],
+ "js": ["borderify.js"]
+ }
+]</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>让浏览器将<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">content scripts</a>加载到匹配网址的网站上</p>
+
+<p>此键(content_scripts)是一个数组,每个项目都是一个满足下列条件的对象:</p>
+
+<ul>
+ <li>
+ <p><strong>必须</strong>包含一个名为<strong><code>matches</code></strong>的键,指定要加载脚本的URL的格式</p>
+ </li>
+ <li>
+ <p><strong>可以</strong>包含一个名为<strong><code>js</code></strong>或<strong><code>css</code></strong>的键,<span>列出要加载到匹配页面的脚本</span></p>
+ </li>
+ <li>
+ <p><strong>可以</strong>包含控制如何加载、何时加载等方面更精细的属性</p>
+ </li>
+</ul>
+
+<p>下面表格列出了所有与你可以使用的键:</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col">名称</th>
+ <th scope="col">类型</th>
+ <th scope="col">描述</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><a id="all_frames" name="all_frames"><code>all_frames</code></a></td>
+ <td><code>Boolean</code></td>
+ <td>
+ <p><code>true</code>: 将<code><a href="#js">js</a></code>和<code><a href="#css">css</a></code>注入该页面所有的框架(frame)中</p>
+
+ <p><code>false</code>: 仅注入到顶层</p>
+
+ <p>默认为false</p>
+ </td>
+ </tr>
+ <tr>
+ <td><a id="css" name="css"><code>css</code></a></td>
+ <td><code>Array</code></td>
+ <td>
+ <p>一个数组,包含将会被注入到匹配页面的CSS文件的路径(路径相对于manifest.json)。</p>
+
+ <p>在加载DOM之前,文件将会按指定的顺序注入。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><a id="exclude_globs" name="exclude_globs"><code>exclude_globs</code></a></td>
+ <td><code>Array</code></td>
+ <td>
+ <div class="geckoVersionNote">Firefox 自48版本开始支持globs</div>
+
+ <p><span class="short_text" id="result_box" lang="zh-CN"><span>包含通配符的字符串数组。</span> <span>请参阅下面的<a href="#Matching_URL_patterns">匹配URL格式</a>。</span></span></p>
+ </td>
+ </tr>
+ <tr>
+ <td><a id="exclude_matches" name="exclude_matches"><code>exclude_matches</code></a></td>
+ <td><code>Array</code></td>
+ <td>一个<a href="/en-US/Add-ons/WebExtensions/match_patterns">match patterns</a>的数组,<span class="short_text" id="result_box" lang="zh-CN"><span>请参阅下面的<a href="#Matching_URL_patterns">匹配URL格式</a>。</span></span></td>
+ </tr>
+ <tr>
+ <td><a id="include_globs" name="include_globs"><code>include_globs</code></a></td>
+ <td><code>Array</code></td>
+ <td>
+ <div class="geckoVersionNote">Firefox 自48版本开始支持globs</div>
+ <span class="short_text" id="result_box" lang="zh-CN"><span>包含通配符的字符串数组。</span> <span>请参阅下面的<a href="#Matching_URL_patterns">匹配URL格式</a>。</span></span></td>
+ </tr>
+ <tr>
+ <td><a id="js" name="js"><code>js</code></a></td>
+ <td><code>Array</code></td>
+ <td>
+ <p>一个数组,包含将会被注入到匹配页面的JS文件的路径(路径相对于manifest.json)。</p>
+
+ <p>文件将会按指定的顺序注入。这意味着如果你想在另一个脚本中包含jQuery,可以这样做:</p>
+
+ <pre class="brush: json">
+<code>"js": ["jquery.js", "my-content-script.js"]</code></pre>
+
+ <p>接下来,<code>"my-content-script.js"</code>可以使用jQuery.</p>
+
+ <p><span class="short_text" id="result_box" lang="zh-CN"><span>文件将在<a href="#run_at">run_at</a>指定的时间注入。</span></span></p>
+ </td>
+ </tr>
+ <tr>
+ <td><a id="matches" name="matches"><code>matches</code></a></td>
+ <td><code>Array</code></td>
+ <td>
+ <p>一个<a href="/en-US/Add-ons/WebExtensions/match_patterns">match patterns</a>的数组,<span class="short_text" id="result_box" lang="zh-CN"><span>请参阅下面的<a href="#Matching_URL_patterns">匹配URL格式</a>。</span></span></p>
+
+ <p><span class="short_text" id="result_box" lang="zh-CN"><span>这是唯一的必须键。</span></span></p>
+ </td>
+ </tr>
+ <tr>
+ <td><a id="run_at" name="run_at"><code>run_at</code></a></td>
+ <td><code>String</code></td>
+ <td>
+ <p>此选项指定在<a href="#js">“js”键</a>中的脚本何时被注入。您可以使用下列的三个字符串之一,每个字符串都代表加载文档过程中的不同状态。状态直接对应于{{domxref("Document/readyState", "Document.readyState")}}:</p>
+
+ <ul>
+ <li>“<code>document_start</code>”:对应于正在加载。 <span>DOM仍在加载中。</span></li>
+ <li>“<code>document_end</code>”:对应于可交互。 <span>DOM已完成加载,但脚本和图像等资源可能仍在加载。</span></li>
+ <li>“<code>document_idle</code>”:对应完成。 <span>文档及其所有资源已完成加载。</span></li>
+ </ul>
+
+ <p>默认值为“document_idle”。</p>
+
+ <p>在所有情况下,<a href="#js">js键</a>中的文件都会在<a href="#css">css键</a>中的文件之后注入。</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="匹配URL格式">匹配URL格式</h2>
+
+<p>“content_scripts”键基于URL匹配将content scripts注入到网页上:如果网页的URL与键中的规则匹配,则将注入脚本。“content_scripts”中有四个属性,可以用于此规则:</p>
+
+<ul>
+ <li><code>matches</code>: 一个关于<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns">match patterns</a>的数组</li>
+ <li><code>exclude_matches:</code> 一个关于<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns">match patterns</a>的数组</li>
+ <li><code>include_globs</code>: 一个关于<a href="#globs">globs</a>的数组</li>
+ <li><code>exclude_globs:</code> 一个关于<a href="#globs">globs</a>的数组</li>
+</ul>
+
+<p>要匹配这些属性之一,网址必须与其数组中的至少一个项匹配。例如,指定一个属性:</p>
+
+<pre class="brush: json">"matches": ["*://*.example.org/*", "*://*.example.com/*"]</pre>
+
+<p>"http://example.org/"和"http://example.com/"都将会匹配</p>
+
+<p>由于matches是唯一的强制性键,其他三个键用于进一步限制匹配的URL。要匹配作为一个整体的键,网址必须:</p>
+
+<ol>
+ <li>匹配matches属性</li>
+ <li>并且,匹配include_globs属性(如果有)</li>
+ <li>并且,不匹配<code>exclude_matches</code>属性(如果有)</li>
+ <li>并且,不匹配<code>exclude_globs</code>属性(如果有)</li>
+</ol>
+
+<h3 id="globs">globs</h3>
+
+<div class="geckoVersionNote">Firefox 自48版本开始支持globs</div>
+
+<p>glob只是一个可以包含通配符的字符串。 有两种类型的通配符,您可以在一个glob中组合使用它们:</p>
+
+<ul>
+ <li>"*" 匹配零个或多个字符</li>
+ <li>"?" 匹配一个字符</li>
+</ul>
+
+<p><code>例如,"*na?i"</code>会匹配<code>"illuminati"和</code><code>"annunaki"</code>,但不会匹配<code>"sagnarelli"</code>.</p>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json">"content_scripts": [
+ {
+ "matches": ["*://*.mozilla.org/*"],
+ "js": ["borderify.js"]
+ }
+]</pre>
+
+<p>这会将content脚本“borderify.js”插入到“mozilla.org”或其任何子域下的所有页面,无论是HTTP还是HTTPS。</p>
+
+<pre class="brush: json"> "content_scripts": [
+ {
+ "exclude_matches": ["*://developer.mozilla.org/*"],
+ "matches": ["*://*.mozilla.org/*"],
+ "js": ["jquery.js", "borderify.js"]
+ }
+ ]</pre>
+
+<p>这会将两个content脚本插入到“mozilla.org”及其任何子域(除“developer.mozilla.org”外)的所有页面中,无论是通过HTTP还是HTTPS。</p>
+
+<p>content脚本有相同的DOM视图,并按照它们在数组中出现的顺序注入,因此“borderify.js”可以访问由“jquery.js”添加的全局变量。</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.content_scripts")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/default_locale/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/default_locale/index.html
new file mode 100644
index 0000000000..9dc13eec3f
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/default_locale/index.html
@@ -0,0 +1,42 @@
+---
+title: default_locale
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/default_locale
+tags:
+ - default_locale
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/default_locale
+---
+<p>{{AddonSidebar}}</p>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">Type</th>
+ <td><code>String</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>可能发生的:如果存在_locales子目录,必须存在,否则不存在。</td>
+ </tr>
+ <tr>
+ <th scope="row">例子</th>
+ <td>
+ <pre class="brush: json">
+"default_locale": "en"</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>如果扩展名包含_locales目录,则该key必须存在,否则不得存在。它标识 _locales的一个子目录,该子目录将用于查找扩展名的默认字符串。</p>
+
+<p>见 <a href="/en-US/Add-ons/WebExtensions/Internationalization">国际化</a> 。</p>
+
+<h2 id="范例">范例</h2>
+
+<pre class="brush: json">"default_locale": "en"</pre>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.default_locale")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/description/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/description/index.html
new file mode 100644
index 0000000000..9081c82e10
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/description/index.html
@@ -0,0 +1,43 @@
+---
+title: 描述 - description
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/description
+tags:
+ - 描述
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/description
+---
+<div>{{AddonSidebar}}</div>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">值类型</th>
+ <td><code>字符串</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>不强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"description": "附加组件的主要功能特性的简短描述."</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>用于在用户下载安装使用界面中显示的一段简短的关于该附加组件的描述.</p>
+
+<p>关于本地化, 可查看 <a href="/en-US/Add-ons/WebExtensions/Internationalization#Internationalizing_manifest.json">localizable property</a>.</p>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json">"description": "附加组件的主要功能特性的简短描述."</pre>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.description")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/developer/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/developer/index.html
new file mode 100644
index 0000000000..86c16d8da1
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/developer/index.html
@@ -0,0 +1,48 @@
+---
+title: developer
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/developer
+tags:
+ - Developer
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/developer
+---
+<div>{{AddonSidebar}}</div>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">值类型</th>
+ <td><code>对象</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>非强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"developer": {
+ "name": "Walt Whitman",
+ "url": "https://en.wikipedia.org/wiki/Walt_Whitman"
+}</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>插件开发者的名字和主页地址,用于显示在浏览器的用户界面中。</p>
+
+<p>该对象的两个属性都是可选的。如果存在“name”和“url”属性,将会分别覆盖<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/author">author</a>和<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/homepage_url">homepage_url</a>键。这个对象仅仅允许指定一个开发者名字的主页地址。</p>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json">"developer": {
+ "name": "Walt Whitman",
+ "url": "https://en.wikipedia.org/wiki/Walt_Whitman"
+}</pre>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.developer")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/index.html
new file mode 100644
index 0000000000..281382d382
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/index.html
@@ -0,0 +1,140 @@
+---
+title: manifest.json
+slug: Mozilla/Add-ons/WebExtensions/manifest.json
+tags:
+ - JSON
+ - manifest.json
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json
+---
+<div>{{AddonSidebar}}</div>
+
+<div class="blockIndicator note">
+<p>本文描述的是适用于 WebExtensions 的 manifest.json。若您正在寻找适用于 PWA 的 manifest.json 的有关信息,请参考这篇文章:<a href="/zh-CN/docs/Web/Manifest">Web App Manifest</a>。</p>
+</div>
+
+<div><code>manifest.json</code> 是每个 WebExtension 唯一必须包含的元数据文件。</div>
+
+<p>通过使用 <code>manifest.json</code>,您可以指定扩展的基本元数据,例如名称和版本,还可以指定扩展各个方面的功能(例如后台脚本,内容脚本和某些浏览器行为)。</p>
+
+
+<p>它是一个允许使用 "<code>//</code>" 撰写单行注释的、特殊的 <a href="/zh-CN/docs/Glossary/JSON">JSON</a> 文件。</p>
+
+<h2 id="manifest.json_键列表">manifest.json 键列表</h2>
+
+<p>支持的 <code>manifest.json</code> 键如下所示:</p>
+
+<h3 id="简体中文内容">简体中文内容</h3>
+
+<div class="index">{{ListSubpages("/zh-CN/Add-ons/WebExtensions/manifest.json")}}</div>
+
+<h3 id="英文内容">英文内容</h3>
+
+<div class="index">{{ListSubpages("/en-US/Add-ons/WebExtensions/manifest.json")}}</div>
+
+<ul>
+ <li><code>"manifest_version"</code>,<code>"version"</code>,和 <code>"name"</code> 是唯一的强制必填键。</li>
+ <li>如果 "_locales" 目录存在的话,"<code>default_locale"</code> 也必须相应存在,否则不应存在。</li>
+ <li>Google Chrome 不支持 <code>"browser_specific_settings"</code></li>
+</ul>
+
+<h3 id="在运行时访问_manifest.json_键">在运行时访问 manifest.json 键</h3>
+
+<p>你可以在拓展的 JavaScript 代码中通过 {{WebExtAPIRef("runtime.getManifest()")}} 函数访问拓展的 manifest 数据:</p>
+
+<pre class="brush: js; no-line-numbers">browser.runtime.getManifest().version;</pre>
+
+<h2 id="示例">示例</h2>
+
+<p>The block below shows the basic syntax for some common manifest keys.</p>
+
+<div class="blockIndicator note">
+<p><strong>Note:</strong> This is not intended to be used as a copy-paste-ready example. Selecting the keys you'll need depends on the extension you are developing.</p>
+</div>
+
+<p>For complete example extensions, see <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Examples">Example extensions</a>.</p>
+
+<pre class="brush: json;">{
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "addon@example.com",
+ "strict_min_version": "42.0"
+ }
+ },
+
+ "background": {
+ "scripts": ["jquery.js", "my-background.js"],
+ },
+
+ "browser_action": {
+ "default_icon": {
+ "19": "button/geo-19.png",
+ "38": "button/geo-38.png"
+ },
+ "default_title": "Whereami?",
+ "default_popup": "popup/geo.html"
+ },
+
+ "commands": {
+ "toggle-feature": {
+ "suggested_key": {
+ "default": "Ctrl+Shift+Y",
+ "linux": "Ctrl+Shift+U"
+ },
+ "description": "Send a 'toggle-feature' event"
+ }
+ },
+
+ "content_security_policy": "script-src 'self' https://example.com; object-src 'self'",
+
+ "content_scripts": [
+ {
+ "exclude_matches": ["*://developer.mozilla.org/*"],
+ "matches": ["*://*.mozilla.org/*"],
+ "js": ["borderify.js"]
+ }
+ ],
+
+ "default_locale": "en",
+
+ "description": "...",
+
+ "icons": {
+ "48": "icon.png",
+ "96": "icon@2x.png"
+ },
+
+ "manifest_version": 2,
+
+ "name": "...",
+
+ "page_action": {
+ "default_icon": {
+ "19": "button/geo-19.png",
+ "38": "button/geo-38.png"
+ },
+ "default_title": "Whereami?",
+ "default_popup": "popup/geo.html"
+ },
+
+ "permissions": ["webNavigation"],
+
+ "version": "0.1",
+
+ "user_scripts": {
+ "api_script": "apiscript.js",
+ },
+
+ "web_accessible_resources": ["images/my-image.png"]
+}</pre>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>For a full overview of all manifest keys and their sub-keys, see the<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_compatibility_for_manifest.json"> full <code>manifest.json</code> browser compatibility table</a>.</p>
+
+
+
+<p>{{Compat("webextensions.manifest")}}</p>
+
+<h2 id="参见">参见</h2>
+
+<p>{{WebExtAPIRef("permissions")}} JavaScript API</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/manifest_version/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/manifest_version/index.html
new file mode 100644
index 0000000000..9d67a37b89
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/manifest_version/index.html
@@ -0,0 +1,45 @@
+---
+title: manifest_version
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/manifest_version
+tags:
+ - WebExtensions
+ - 拓展
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/manifest_version
+---
+<p>{{AddonSidebar}}</p>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">值类型</th>
+ <td><code>Number</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"manifest_version": 2</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>此键指定扩展使用的 manifest.json 的版本。</p>
+
+<p>目前,此值必须为 2。</p>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json">"manifest_version": 2
+</pre>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.manifest_version")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/name/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/name/index.html
new file mode 100644
index 0000000000..3869571374
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/name/index.html
@@ -0,0 +1,43 @@
+---
+title: 名称 - name
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/name
+tags:
+ - 名称
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/name
+---
+<div>{{AddonSidebar}}</div>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">值类型</th>
+ <td><code>字符串(String)</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"name": "附加组件的名称"</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>附加组件的名称. 用于在用户界面和 addons.mozilla.org 网站上显示标识名称.</p>
+
+<p>关于本地化, 可查看 <a href="/en-US/Add-ons/WebExtensions/Internationalization#Internationalizing_manifest.json">localizable property</a>.</p>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json">"name": "插件的名称"</pre>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.name")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/permissions/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/permissions/index.html
new file mode 100644
index 0000000000..f26782540e
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/permissions/index.html
@@ -0,0 +1,182 @@
+---
+title: 权限 - permissions
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/permissions
+tags:
+ - 权限
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/permissions
+---
+<p>{{AddonSidebar}}</p>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">值类型</th>
+ <td><code>数组</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>不强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json notranslate">
+"permissions": [
+ "*://developer.mozilla.org/*",
+ "webRequest"
+]</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>使用permissions 关键字为你的扩展请求特殊的权限。该关键字为一个字符串数列,每个字符串请求一项权限。</p>
+
+<p>如果你使用该关键字请求权限,浏览器可能会在安装该扩展时通知用户该扩展需求某些权限,并询问他们是否愿意给予这些权限。在插件安装之后浏览器也可能允许用户检查扩展的权限。因为要求授予权限可能会影响用户安装你的扩展的意愿,所以请求权限需要特别小心的考虑。举个例子,你想要避免请求不必要的权限,而且可以在你的扩展描述中提供你为何需要某些权限的信息。更多关于这个话题的描述你可以参考这篇提供的文章 <a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Request_the_right_permissions">请求正确的权限</a>。</p>
+
+<p>该关键字能够包含三种类型的权限:</p>
+
+<ul>
+ <li>主机权限</li>
+ <li>API 权限</li>
+ <li>活动标签权限</li>
+</ul>
+
+<h2 id="主机权限">主机权限</h2>
+
+<p> 主机权限使用 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns">match patterns </a>指定,扩展在每一个表达式指定的网址上请求额外权限。</p>
+
+<p>额外权限包括:</p>
+
+<ul>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a> 和 <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">fetch</a> 用于访问无跨源限制的源文件(包括从content scripts发出的访问请求)</li>
+ <li>以编程方式(使用 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript">tabs.executeScript</a>)将脚本注入到来自源服务器(origins)提供的页面的功能。</li>
+ <li>使用 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest">webRequest</a> 在其主机上获取消息的能力。</li>
+ <li>使用 <a href="/en-US/Add-ons/WebExtensions/API/cookies">cookies</a> API 访问主机cookies的能力,只要 cookies api的权限也被请求。</li>
+ <li>使用无通配符(*)的全域名会绕开跟踪保护机制,但不能与 <code>&lt;all_urls&gt;</code> 共用.</li>
+</ul>
+
+<p>Firefox浏览器,自56以后的版本,扩展都会自动获取其源的主机权限,如以下形式:</p>
+
+<pre class="notranslate"><code>moz-extension://60a20a9b-1ad4-af49-9b6c-c64c98c37920/</code></pre>
+
+<p><code>60a20a9b-1ad4-af49-9b6c-c64c98c37920</code> 是扩展内部ID。编程时可使用 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/extension/getURL">extension.getURL()</a> 来返回此URL路径:</p>
+
+<ol>
+ <li>
+ <pre class="notranslate"><code>browser.extension.getURL("");
+// </code><code>moz-extension://60a20a9b-1ad4-af49-9b6c-c64c98c37920/</code></pre>
+ </li>
+</ol>
+
+<h2 id="API_权限">API 权限</h2>
+
+<p>API 权限有关键字指定,每个关键字标志着一类WebExtension API 能够被使用。</p>
+
+<p>如下关键字是当前可用的:</p>
+
+<ul>
+ <li><code>activeTab</code></li>
+ <li><code>alarms</code></li>
+ <li><code>bookmarks</code></li>
+ <li><code>browsingData</code></li>
+ <li><code>browserSettings</code></li>
+ <li><code>contextMenus</code></li>
+ <li><code>contextualIdentities</code></li>
+ <li><code>cookies</code></li>
+ <li><code>downloads</code></li>
+ <li><code>downloads.open</code></li>
+ <li><code>find</code></li>
+ <li><code>geolocation</code></li>
+ <li><code>history</code></li>
+ <li><code>identity</code></li>
+ <li><code>idle</code></li>
+ <li><code>management</code></li>
+ <li><code>menus</code></li>
+ <li><code>nativeMessaging</code></li>
+ <li><code>notifications</code></li>
+ <li><code>pkcs11</code></li>
+ <li><code>privacy</code></li>
+ <li><code>proxy</code></li>
+ <li><code>sessions</code></li>
+ <li><code>storage</code></li>
+ <li><code>tabs</code></li>
+ <li><code>theme</code></li>
+ <li><code>topSites</code></li>
+ <li><code>webNavigation</code></li>
+ <li><code>webRequest</code></li>
+ <li><code>webRequestBlocking</code></li>
+</ul>
+
+<p>在大部分情况下这种权限仅仅允许你访问API,除了以下情况:</p>
+
+<ul>
+ <li><code>tabs</code>让你可以访问 <a href="/en-US/Add-ons/WebExtensions/API/tabs"><code>一部分特权API</code></a>: <code>Tab.url</code>, <code>Tab.title</code>, and <code>Tab.faviconUrl</code>。在Firefox中你也需要<code>tabs </code>来将queryInfo中的url参数加入 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query">tabs.query()</a></code>. 剩余的<code>tabs</code> API能在不要求任何权限的情况被使用</li>
+ <li><code>webRequestBlocking</code> 允许你是用“blocking”参数,所以你可以<a href="/en-US/Add-ons/WebExtensions/API/WebRequest"> 修改或取消requests</a>.</li>
+ <li><code>downloads.open</code> 让你使用 {{WebExtAPIRef("downloads.open()")}} API.</li>
+</ul>
+
+<h2 id="活动标签权限">活动标签权限</h2>
+
+<p>该权限被指定为<code>“activeTab”</code>。如果一个扩展拥有<code>activeTab</code>权限,当用户跟该扩展交互时,扩展仅在活动标签被赋予额外权限。</p>
+
+<p>“用户交互”包括:</p>
+
+<ul>
+ <li>用户点击扩展的浏览器按钮或者页面按钮</li>
+ <li>用户选择了扩展的上下文菜单</li>
+ <li>用户敲击了扩展定义的快捷键</li>
+</ul>
+
+<p>额外特权包括:</p>
+
+<ul>
+ <li>插入JavaScript或者CSS的能力, 使用 <code><a href="/en-US/Add-ons/WebExtensions/API/tabs/executeScript">browser.tabs.executeScript</a></code> 和 <code><a href="/en-US/Add-ons/WebExtensions/API/tabs/insertCSS">browser.tabs.insertCSS</a></code></li>
+ <li>为当前标签访问tabs API权限部分的能力,包括:Tab.url,Tab.title, 和Tab .faviconUrl。</li>
+</ul>
+
+<p>改权限的目的是为了在不给予扩展太多权限的情况下,使得扩展能够应付大部分情况。很多扩展需要在用户要求时,在当前页面做一些处理,比如,考虑一个扩展想要在用户点击一个浏览器按钮时在当前页面运行一个脚本,如果 activeTab 权限不存在,扩展将需要请求主机权限&lt;all_urls&gt;,但是这给予了扩展超过其需要的权限:现在它可以在任何任何时间标签页执行脚本任何次,而不是仅仅在活动标签而且仅仅回应用户的行为。</p>
+
+<h2 id="剪贴板访问">剪贴板访问</h2>
+
+<p>有两种权限使得WebExtentsion可以跟剪贴板交互:</p>
+
+<ul>
+ <li><code>clipboardWrite</code>: 使用<code>document.execCommand("copy")</code> 或<code>document.execCommand("cut")</code> 向剪贴板写入</li>
+ <li><code>clipboardRead</code>: 使用 <code>document.execCommand("paste")</code> 从剪贴板读取</li>
+</ul>
+
+<p>查看 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Interact_with_the_clipboard">Interact with the clipboard</a> 获取更多</p>
+
+<h2 id="无限制存储">无限制存储</h2>
+
+<p><code>unlimitedStorage</code> 权限:</p>
+
+<ul>
+ <li>能使扩展突破{{WebExtAPIRef("storage.local")}} API设定的quota限制</li>
+ <li>Firefox浏览器中,无须提示用户授权,便可帮助扩展创建永久保存的IndexedDB数据库 <a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria#Firefox_specifics">"persistent" IndexedDB database</a></li>
+</ul>
+
+<dl>
+</dl>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json notranslate"> "permissions": ["*://developer.mozilla.org/*"]</pre>
+
+<p>请求 developer.mozilla.org 下的权限访问.</p>
+
+<pre class="brush: json notranslate"> "permissions": ["tabs"]</pre>
+
+<p>请求tabs API的权限需要部分的访问。</p>
+
+<pre class="brush: json notranslate"> "permissions": ["*://developer.mozilla.org/*", "tabs"]</pre>
+
+<p>请求以上两种访问。</p>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p>本页的兼容列表是从结构化数据生成的。如果你想参与修改此数据,请参考 <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 并发送pull 请求。</p>
+
+<p>{{Compat("webextensions.manifest.permissions")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/short_name/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/short_name/index.html
new file mode 100644
index 0000000000..444dac6eaa
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/short_name/index.html
@@ -0,0 +1,43 @@
+---
+title: 短名称 - short_name
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/short_name
+tags:
+ - 短名称
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/short_name
+---
+<div>{{AddonSidebar}}</div>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">Type</th>
+ <td><code>String</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>不强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"short_name": "附加组件的短名称"</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>附加组件的短名称. 一般用在 <a href="/en-US/Add-ons/WebExtensions/manifest.json/name">name</a> 特性太长的情况下. 建议短名称的长度不要超过12个字符. 如果没有在 manifest.json 主文件中声明 short_name, 并且 name 特性的值又比较长的话, 用户界面显示的时候可能只会显示一部分. </p>
+
+<p>关于本地化, 可查看 <a href="/en-US/Add-ons/WebExtensions/Internationalization#Internationalizing_manifest.json">localizable property</a>.</p>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json">"short_name": "附加组件的短名称"</pre>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.short_name")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/version/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/version/index.html
new file mode 100644
index 0000000000..98028f9235
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/version/index.html
@@ -0,0 +1,49 @@
+---
+title: version
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/version
+tags:
+ - version
+ - 版本信息
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/version
+---
+<p>{{AddonSidebar}}</p>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">Type</th>
+ <td><code>String</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"version": "0.1"</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>附加组件的版本, 一般格式设置为由点分隔开来数字的ASCII字符串. 关于版本格式的详细信息, 请查看 <a href="https://developer.mozilla.org/en-US/docs/Toolkit_version_format">Version format</a> .</p>
+
+<p>需要注意的是 Chrome 浏览器的 version 格式要求(<a href="https://developer.chrome.com/extensions/manifest/version">the syntax defined for Chrome's <code>version</code></a>)比 Firefox 浏览器的 version 格式更严格一些, 这意味这:</p>
+
+<ul>
+ <li>对 Chrome 浏览器有效的 version 特性的值一定在 Firefox 浏览器中有效</li>
+ <li>但对 Firefox 浏览器有效的 version 特性的值在 Chrome 浏览器中却不一定有效</li>
+</ul>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json">"version": "0.1"</pre>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.version")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/web_accessible_resources/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/web_accessible_resources/index.html
new file mode 100644
index 0000000000..713741a26b
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/web_accessible_resources/index.html
@@ -0,0 +1,96 @@
+---
+title: web_accessible_resources
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/web_accessible_resources
+tags:
+ - 扩展应用
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/web_accessible_resources
+---
+<p>{{AddonSidebar}}</p>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">类型</th>
+ <td><code>Array</code></td>
+ </tr>
+ <tr>
+ <th scope="row">是否必需</th>
+ <td>No</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json no-line-numbers">
+"web_accessible_resources": [
+ "images/my-image.png"
+]</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="描述">描述</h2>
+
+<p>你有时想将资源(如图片、HTML、CSS 或 JavaScript)与你的扩展应用合并打包,让网页能够访问它们。</p>
+
+<p>举个例子,<a href="https://github.com/mdn/webextensions-examples/tree/master/beastify">Beastify example extension</a> 将用户选择的野兽图片来替换网页,这些图片与应用是经过合并打包的。该应用添加 <code><a href="/en-US/docs/Web/HTML/Element/img">&lt;img&gt;</a></code>,其 <code>src</code> 指向图片,这样就使选中的图片可见了。网页要载入图片的话,这些图片就必须可经访问。</p>
+
+<p>通过 <code>web_accessible_resources</code>, 你列出资源,让它们可经网页访问。这些资源路径相对于 manifest.json 文件.</p>
+
+<p>注意,这其中不必包括 content scripts。</p>
+
+<p>如果你的应用要用 {{WebExtAPIRef("webRequest")}} 来重定向公共 URL(如 HTTPS) 到一个该应用中的页面, 那么应用必须将该页面列入<code>web_accessible_resources</code>。</p>
+
+<h3 id="使用_web_accessible_resources">使用 web_accessible_resources</h3>
+
+<p>例如,如果你的应用含有图片,路径为 images/my-image.png,如下所示:</p>
+
+<pre class="no-line-numbers">my-extension-files/
+ manifest.json
+ my-background-script.js
+ images/
+ my-image.png</pre>
+
+<p>如果要使网页能够从元素 <code><a href="/en-US/docs/Web/HTML/Element/img">&lt;img&gt;</a></code> 的属性 <code>src</code> 指向该图片,你得写明<code>web_accessible_resources</code>,如下所示:</p>
+
+<pre class="brush: json no-line-numbers">"web_accessible_resources": ["images/my-image.png"]</pre>
+
+<p>之后,图片可通过 URL 来访问,如下所示:</p>
+
+<pre class="no-line-numbers">moz-extension://&lt;extension-UUID&gt;/images/my-image.png"</pre>
+
+<p><code>&lt;extension-UUID&gt;</code> 不是应用 ID,它随机生成,对应每个浏览器实例,以防网页查看浏览器安装的扩展应用来获取信息。</p>
+
+<div class="blockIndicator note">
+<p>Chrome 的 <code>&lt;extension-UUID&gt;</code> 是不变的。某资源如果由<code>web_accessible_resources</code> 写明,那么它可通过 <code>chrome-extension://&lt;your-extension-id&gt;/&lt;path/to/resource&gt;</code> 来访问。  </p>
+</div>
+
+<p>要获得资源的 URL,推荐用 <code><a href="/en-US/Add-ons/WebExtensions/API/runtime/getURL">runtime.getURL</a></code> 向参数传递 manifest.json 的相对路径,比如:</p>
+
+<pre class="brush: js no-line-numbers">browser.runtime.getURL("images/my-image.png");
+// something like:
+// moz-extension://944cfddf-7a95-3c47-bd9a-663b3ce8d699/images/my-image.png</pre>
+
+<p>这会返回正确的 URL,不受应用运行的浏览器影响。</p>
+
+<h3 id="通配符">通配符</h3>
+
+<p><code>web_accessible_resources</code>  中的条目还可以有通配符。比如,下面的条目匹配“images/my-image.png”:</p>
+
+<pre class="brush: json no-line-numbers"> "web_accessible_resources": ["images/*.png"]</pre>
+
+<h3 id="安全">安全</h3>
+
+<p>注意,如果你部署了一个页面,那么任一网页可能会链接或重定向至该页面,因而它应认为任意输入(比如 POST data)的来源不可信任,这与通常网页的做法一样。</p>
+
+<h2 id="Example">Example</h2>
+
+<pre class="brush: json no-line-numbers">"web_accessible_resources": ["images/my-image.png"]</pre>
+
+<p>Make the file at "images/my-image.png" web accessible.</p>
+
+<h2 id="Browser_compatibility">Browser compatibility</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.web_accessible_resources")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/主页地址/index.html b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/主页地址/index.html
new file mode 100644
index 0000000000..01749d5ff3
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/manifest.json/主页地址/index.html
@@ -0,0 +1,42 @@
+---
+title: homepage_url
+slug: Mozilla/Add-ons/WebExtensions/manifest.json/主页地址
+translation_of: Mozilla/Add-ons/WebExtensions/manifest.json/homepage_url
+---
+<div>{{AddonSidebar}}</div>
+
+<table class="fullwidth-table standard-table">
+ <tbody>
+ <tr>
+ <th scope="row" style="width: 30%;">值类型</th>
+ <td><code>字符串(String)</code></td>
+ </tr>
+ <tr>
+ <th scope="row">强制性</th>
+ <td>非强制</td>
+ </tr>
+ <tr>
+ <th scope="row">示例</th>
+ <td>
+ <pre class="brush: json">
+"homepage_url": "https://example.org/my-addon"</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>该扩展的主页地址。</p>
+
+<p>如果 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json/developer">developer</a> 键存在且包含“url”属性,它将会覆盖 <code>homepage_url</code> 键。</p>
+
+<p>这是一个 <a href="/en-US/Add-ons/WebExtensions/Internationalization#Internationalizing_manifest.json">localizable property</a>.</p>
+
+<h2 id="示例">示例</h2>
+
+<pre class="brush: json">"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify"</pre>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<p class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
+
+<p>{{Compat("webextensions.manifest.homepage_url")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/match_patterns/index.html b/files/zh-cn/mozilla/add-ons/webextensions/match_patterns/index.html
new file mode 100644
index 0000000000..44df7ebb7f
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/match_patterns/index.html
@@ -0,0 +1,384 @@
+---
+title: 匹配模式
+slug: Mozilla/Add-ons/WebExtensions/Match_patterns
+tags:
+ - Match_patterns
+ - URIs
+ - urls
+translation_of: Mozilla/Add-ons/WebExtensions/Match_patterns
+---
+<div>{{AddonSidebar}}</div>
+
+<p>匹配模式是一种指定网址组的方法:: 一个匹配模式匹配特定的一组URL。 它们由WebExtensions 在几个地方使用,最明显的是指定要将<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">内容脚本</a>加载到哪些文档中,并指定要向其中添加 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/API/webRequest">webRequest </a>侦听器的URL。</p>
+
+<p>使用匹配模板的API通常接收一个匹配模板的列表,当URL匹配任何模式时会恰当的运行. 看个例子 在manifest.json中的 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts">content_scripts</a></code> 关键字。</p>
+
+<h2 id="匹配模式结构">匹配模式结构</h2>
+
+<p>所有的匹配模式用一个字符串来定义,而且都是<a href="/en-US/Add-ons/WebExtensions/Match_patterns#%3Call_urls%3E">"&lt;all_urls&gt;"</a> 模板的一部份, 匹配模板包含三个部分: <em>scheme</em>, <em>host</em>, 和 <em>path</em>.  scheme  host 用 "://" 分隔。</p>
+
+<pre>&lt;scheme&gt;://&lt;host&gt;&lt;path&gt;</pre>
+
+<h3 id="方案">方案</h3>
+
+<p> <em>scheme</em>  可能以下两种格式之一:</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col" style="width: 50%;">Form</th>
+ <th scope="col">Matches</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>"*"</td>
+ <td>Only "http" and "https".</td>
+ </tr>
+ <tr>
+ <td>One of "http", "https", "file", "ftp", "app".</td>
+ <td>Only the given scheme.</td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="主机">主机</h3>
+
+<p> <em>host </em>组件可以采取三种形式之一::</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col" style="width: 50%;">Form</th>
+ <th scope="col">Matches</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>"*"</td>
+ <td>Any host.</td>
+ </tr>
+ <tr>
+ <td>"*." followed by part of the hostname.</td>
+ <td>The given host and any of its subdomains.</td>
+ </tr>
+ <tr>
+ <td>A complete hostname, without wildcards.</td>
+ <td>Only the given host.</td>
+ </tr>
+ </tbody>
+</table>
+
+<p>只有当 <em>scheme</em> 是 "file" 是 <em>host</em> 可选的</p>
+
+<p>值得注意的是通配符可能只会在开头显示。</p>
+
+<h3 id="路径">路径</h3>
+
+<p><em>path </em>组件必须以“/”开头。</p>
+
+<p>之后,它可能随后包含“*”通配符和网址路径中允许的任何字符的任意组合。 与 <em>host </em>不同, <em>path </em>组件可能在中间或末尾包含“*”通配符,并且“*”通配符可以多次出现。</p>
+
+<h3 id="&lt;all_urls>">&lt;all_urls&gt;</h3>
+
+<p>特殊值“&lt;all_urls&gt;”匹配任何受支持方案下的所有URL:即, "http", "https", "file", "ftp", "app"。</p>
+
+<h2 id="范例">范例</h2>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col" style="width: 33%;">Pattern</th>
+ <th scope="col" style="width: 33%;">Example matches</th>
+ <th scope="col" style="width: 33%;">Example non-matches</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>
+ <p><code>&lt;all_urls&gt;</code></p>
+
+ <p>Match all URLs.</p>
+ </td>
+ <td>
+ <p><code>http://example.org/</code></p>
+
+ <p><code>ftp://files.somewhere.org/</code></p>
+
+ <p><code>https://a.org/some/path/</code></p>
+ </td>
+ <td>
+ <p><code>resource://a/b/c/</code><br>
+ (unsupported scheme)</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><code>*://*.mozilla.org/*</code></p>
+
+ <p>Match all HTTP and HTTPS URLs that are hosted at "mozilla.org" or one of its subdomains.</p>
+ </td>
+ <td>
+ <p><code>http://mozilla.org/</code></p>
+
+ <p><code>https://mozilla.org/</code></p>
+
+ <p><code>http://a.mozilla.org/</code></p>
+
+ <p><code>http://a.b.mozilla.org/</code></p>
+
+ <p><code>https://b.mozilla.org/path/</code></p>
+ </td>
+ <td>
+ <p><code>ftp://mozilla.org/</code><br>
+ (unmatched scheme)</p>
+
+ <p><code>http://mozilla.com/</code><br>
+ (unmatched host)</p>
+
+ <p><code>http://firefox.org/</code><br>
+ (unmatched host)</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><code>*://mozilla.org/</code></p>
+
+ <p>Match all HTTP and HTTPS URLs that are hosted at exactly "mozilla.org/".</p>
+ </td>
+ <td>
+ <p><code>http://mozilla.org/</code></p>
+
+ <p><code>https://mozilla.org/</code></p>
+ </td>
+ <td>
+ <p><code>ftp://mozilla.org/</code><br>
+ (unmatched scheme)</p>
+
+ <p><code>http://a.mozilla.org/</code><br>
+ (unmatched host)</p>
+
+ <p><code>http://mozilla.org/a</code><br>
+ (unmatched path)</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><code>ftp://mozilla.org/</code></p>
+
+ <p>Match only "ftp://mozilla.org/".</p>
+ </td>
+ <td><code>ftp://mozilla.org</code></td>
+ <td>
+ <p><code>http://mozilla.org/</code><br>
+ (unmatched scheme)</p>
+
+ <p><code>ftp://sub.mozilla.org/</code><br>
+ (unmatched host)</p>
+
+ <p><code>ftp://mozilla.org/path</code><br>
+ (unmatched path)</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><code>https://*/path</code></p>
+
+ <p>Match HTTPS URLs on any host, whose path is "path".</p>
+ </td>
+ <td>
+ <p><code>https://mozilla.org/path</code></p>
+
+ <p><code>https://a.mozilla.org/path</code></p>
+
+ <p><code>https://something.com/path</code></p>
+ </td>
+ <td>
+ <p><code>http://mozilla.org/path</code><br>
+ (unmatched scheme)</p>
+
+ <p><code>https://mozilla.org/path/</code><br>
+ (unmatched path)</p>
+
+ <p><code>https://mozilla.org/a</code><br>
+ (unmatched path)</p>
+
+ <p><code>https://mozilla.org/</code><br>
+ (unmatched path)</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><code>https://*/path/</code></p>
+
+ <p>Match HTTPS URLs on any host, whose path is "path/".</p>
+ </td>
+ <td>
+ <p><code>https://mozilla.org/path/</code></p>
+
+ <p><code>https://a.mozilla.org/path/</code></p>
+
+ <p><code>https://something.com/path</code>/</p>
+ </td>
+ <td>
+ <p><code>http://mozilla.org/path/</code><br>
+ (unmatched scheme)</p>
+
+ <p><code>https://mozilla.org/path</code><br>
+ (unmatched path)</p>
+
+ <p><code>https://mozilla.org/a</code><br>
+ (unmatched path)</p>
+
+ <p><code>https://mozilla.org/</code><br>
+ (unmatched path)</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><code>https://mozilla.org/*</code></p>
+
+ <p>Match HTTPS URLs only at "mozilla.org", with any path.</p>
+ </td>
+ <td>
+ <p><code>https://mozilla.org/</code></p>
+
+ <p><code>https://mozilla.org/path</code></p>
+
+ <p><code>https://mozilla.org/another</code></p>
+
+ <p><code>https://mozilla.org/path/to/doc</code></p>
+ </td>
+ <td>
+ <p><code>http://mozilla.org/path</code><br>
+ (unmatched scheme)</p>
+
+ <p><code>https://mozilla.com/path</code><br>
+ (unmatched host)</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><code>https://mozilla.org/a/b/c/</code></p>
+
+ <p>Match only this URL.</p>
+ </td>
+ <td><code>https://mozilla.org/a/b/c/</code></td>
+ <td>Anything else.</td>
+ </tr>
+ <tr>
+ <td>
+ <p><code>https://mozilla.org/*/b/*/</code></p>
+
+ <p>Match HTTPS URLs hosted on "mozilla.org", whose path contains a component "b" somewhere in the middle.</p>
+ </td>
+ <td>
+ <p><code>https://mozilla.org/a/b/c/</code></p>
+
+ <p><code>https://mozilla.org/d/b/f/</code></p>
+
+ <p><code>https://mozilla.org/a/b/c/d/</code></p>
+ </td>
+ <td>
+ <p><code>https://mozilla.org/b/*/</code><br>
+ (unmatched path)</p>
+
+ <p><code>https://mozilla.org/a/b/</code><br>
+ (unmatched path)</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><code>file:///blah/*</code></p>
+
+ <p>Match any FILE URL whose path begins with "blah".</p>
+ </td>
+ <td>
+ <p><code>file:///blah/</code></p>
+
+ <p><code>file:///blah/bleh</code></p>
+ </td>
+ <td><code>file:///bleh/</code><br>
+ (unmatched path)</td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="无效匹配模式">无效匹配模式</h3>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Invalid pattern</th>
+ <th scope="col">Reason</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>resource://path/</code></td>
+ <td>Unsupported scheme.</td>
+ </tr>
+ <tr>
+ <td><code>https://mozilla.org</code></td>
+ <td>No path.</td>
+ </tr>
+ <tr>
+ <td><code>https://mozilla.*.org/</code></td>
+ <td>"*" in host must be at the start.</td>
+ </tr>
+ <tr>
+ <td><code>https://*zilla.org/</code></td>
+ <td>"*" in host must by the only character or be followed by ".".</td>
+ </tr>
+ <tr>
+ <td><code>http*://mozilla.org/</code></td>
+ <td>"*" in scheme must be the only character.</td>
+ </tr>
+ <tr>
+ <td><code>file://*</code></td>
+ <td>Empty path: this should be "<code>file:///*</code>".</td>
+ </tr>
+ </tbody>
+</table>
+
+<h2 id="测试匹配模式">测试匹配模式</h2>
+
+<p>当制作扩展时你通常不会跟直接使用匹配模板: 通常你讲一个匹配模式传递给API,然后API构造一个匹配模式并且使用他来测试url。不过如果你正在尝试哪一种匹配模式可以被使用,或者调试一个匹配问题,那么直接创建和测试匹配模板的能力将变得有用,这个模块将解释如何做到这点。</p>
+
+<p>首先,打开开发者工具设置,并且检查 "Enable browser chrome and add-on debugging toolboxes" 被打开:</p>
+
+<p>{{EmbedYouTube("JDEe2fyFpHE")}}</p>
+
+<p>然后打开 "Browser Console":</p>
+
+<p>{{EmbedYouTube("mfuBMje6dA4")}}</p>
+
+<p>它给了你一个命令行以使你可以执行一些特权javascript代码。</p>
+
+<div class="warning">
+<p>因为运行在浏览器控制台的代码拥有系统特权,在任何时候都请你小心理解你的代码做了什么</p>
+</div>
+
+<p>现在粘贴以下代码到命令行然后按下 <kbd>enter</kbd>:</p>
+
+<pre class="brush: js">Cu.import("resource://gre/modules/MatchPattern.jsm");
+Cu.import("resource://gre/modules/BrowserUtils.jsm");</pre>
+
+<p>这做了两件事:</p>
+
+<ul>
+ <li>导入 "MatchPattern.jsm": 这是实现了匹配模板的系统模块,特别的,这个模块包含了 <code>MatchPattern</code> 对象. <code>MatchPattern</code> 对象定义了一个 <code>matches()</code> 方法, 他需要一个URL然后返回 <code>true</code> 或者 <code>false</code>.</li>
+ <li>导入 "BrowserUtils.jsm": 包含了一个方法 <code>makeURI()</code>, 他转换一个字符串为一个 <code><a href="/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIURI">nsIURI</a></code> 对象. <code>nsIURI</code> 是 <code>matches()</code> 方法需要接受的一个参数。</li>
+</ul>
+
+<p>现在你可以构造MatchPattern对象,构造URIs,并检查URIs 是否匹配:</p>
+
+<pre class="brush: js">var match = new MatchPattern("*://mozilla.org/");
+
+var uri = BrowserUtils.makeURI("https://mozilla.org/");
+match.matches(uri); // &lt; true
+
+uri = BrowserUtils.makeURI("https://mozilla.org/path");
+match.matches(uri); // &lt; false</pre>
+
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/modify_a_web_page/index.html b/files/zh-cn/mozilla/add-ons/webextensions/modify_a_web_page/index.html
new file mode 100644
index 0000000000..9f4856de63
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/modify_a_web_page/index.html
@@ -0,0 +1,239 @@
+---
+title: 修改web页面
+slug: Mozilla/Add-ons/WebExtensions/Modify_a_web_page
+translation_of: Mozilla/Add-ons/WebExtensions/Modify_a_web_page
+---
+<div>{{AddonSidebar}}</div>
+
+<p>浏览器附加组件( add-on )常被用于修改网页。例如更改页面的样式,隐藏特定的DOM节点或把DOM节点注入到页面中。</p>
+
+<p>使用WebExtensions有两种方式:</p>
+
+<ul>
+ <li>声明方式:定义一个网址格式,用来匹配特定的网址,然后加载脚本到对应的网页中.</li>
+ <li>编程方式: 使用JavaScript 接口, 将脚本加载到一个指定标签页所承载的页面中</li>
+</ul>
+
+<p>无论使用上面何种方式,它们都被称为内容脚本, 与其他脚本的区别:</p>
+
+<ul>
+ <li>只能使用一部分的webextension API。</li>
+ <li>能读取加载了内容脚本的网页。</li>
+ <li>通过使用消息API与其他的webextension通信。</li>
+</ul>
+
+<p>在本文中,我们将看下加载脚本的两种方式。</p>
+
+<h2 id="修改匹配URL的页面">修改匹配URL的页面</h2>
+
+<p>首先,创建一个名为“ modify-page ”的文件夹,并在目录下创建“ manifest.json ”文件,内容如下:</p>
+
+<pre class="brush: json">{
+
+ "manifest_version": 2,
+ "name": "modify-page",
+ "version": "1.0",
+
+ "content_scripts": [
+ {
+ "matches": ["https://developer.mozilla.org/*"],
+ "js": ["page-eater.js"]
+ }
+ ]
+
+}</pre>
+
+<p>"content_scripts"指出符合 URL 格式的页面地址,然后让浏览器加载脚本(“ page-eater.js“)到匹配的URL页面(<a href="https://developer.mozilla.org/">https://developer.mozilla.org/</a> )。</p>
+
+<div class="note">
+<p><span id="result_box" lang="zh-CN"><span>由于</span></span> <code>content_scripts</code> <span lang="zh-CN"><span>的</span></span> <code>"js"</code> <span lang="zh-CN"><span>属性是一个数组,因此可以使用它将多个脚本注入匹配的页面。</span> <span>如果这样做,页面将按照数组中列出的顺序加载多个脚本。</span></span></p>
+</div>
+
+<div class="note">
+<p><code>content_scripts</code> <span class="short_text" lang="zh-CN"><span>键还具有一个</span></span> <code>"css"</code> <span class="short_text" lang="zh-CN"><span>属性,可以使用它来注入CSS样式表。</span></span></p>
+</div>
+
+<p>在 "modify-page" 文件夹下创建“ page-eater.js ”文件,内容如下:</p>
+
+<pre class="brush: js">document.body.textContent = "";
+
+var header = document.createElement('h1');
+header.textContent = "This page has been eaten";
+document.body.appendChild(header);</pre>
+
+<p>现在安装这个<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">WebExtension</a>, 然后浏览 <a href="https://developer.mozilla.org/">https://developer.mozilla.org/</a>:</p>
+
+<p>{{EmbedYouTube("lxf2Tkg6U1M")}}</p>
+
+<div class="note">
+<p><span id="result_box" lang="zh-CN"><span>请注意,虽然此视频显示在</span></span> <a href="https://addons.mozilla.org/en-US/firefox/">addons.mozilla.org</a> <span lang="zh-CN"><span>工作的</span></span> content scripts <span lang="zh-CN"><span>,但目前该网站已禁止</span></span> content scripts <span lang="zh-CN"><span>。</span></span></p>
+</div>
+
+<h2 id="通过程序修改页面">通过程序修改页面</h2>
+
+<p>如何修改程序使其在用户要求时才吞页面。现在修改上面的例子,在点击右键菜单项时才注入内容脚本。</p>
+
+<p>修改 "manifest.json" 内容如下:</p>
+
+<pre class="brush: json">{
+
+ "manifest_version": 2,
+ "name": "modify-page",
+ "version": "1.0",
+
+ "permissions": [
+ "activeTab",
+ "contextMenus"
+ ],
+
+ "background": {
+ "scripts": ["background.js"]
+ }
+
+}</pre>
+
+<p>这里我们要移除"<code>content_scripts</code>"键值,并添加两个键:</p>
+
+<ul>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code>:要向页面中注入脚本,就需要拥有修改页面对应的权限。<a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission"><code>activeTab</code></a>可以临时获得修改当前活动标签所加载的页面的权限。 另外还通过 contextmenus 来获取添加右键菜单项的权限。</li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/background">background</a></code>: 加载名为 "background.js" 的 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Anatomy_of_a_WebExtension#Background_scripts">"background script"</a> (长期有效的后台脚本),在该脚本中,我们将设置注入右键菜单的内容脚本。</li>
+</ul>
+
+<p>在 "modify-page" 文件夹下创建名为 "background.js"的新文件,内容如下:</p>
+
+<pre class="brush: js">browser.contextMenus.create({
+ id: "eat-page",
+ title: "Eat this page"
+});
+
+browser.contextMenus.onClicked.addListener(function(info, tab) {
+ if (info.menuItemId == "eat-page") {
+ browser.tabs.executeScript({
+ file: "page-eater.js"
+ });
+ }
+});
+</pre>
+
+<p>在该脚本中我们创建了一个右键菜单项, 给了它一个具体的 id 和标题 (将在菜单中显示的文本)。 然后又设置了一个事件侦听器,当用户点击菜单项时,检查该菜单项是否就是我们的吞页菜单项。 如果是, 就通过<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript">tabs.executeScript()</a></code> 接口,把"page-eater.js" 注入到活动标签页中。 这个接口用标签ID做为参数:如果省略标签ID参数,就默认把脚本注入当前活动标签。</p>
+
+<p>现在,附加组件看起来像这样:</p>
+
+<pre class="line-numbers language-html"><code class="language-html">modify-page/
+ background.js
+ manifest.json
+ page-eater.js</code></pre>
+
+<p>重新加载<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox#Reloading_a_temporary_add-on">WebExtension</a>, 打开页面 (这次可以是任何一个页面) 激活右键菜单,然后选择 "Eat this page":</p>
+
+<p>{{EmbedYouTube("zX4Bcv8VctA")}}</p>
+
+<div class="note">
+<p><span id="result_box" lang="zh-CN"><span>请注意,虽然此视频显示在</span></span> <a href="https://addons.mozilla.org/en-US/firefox/">addons.mozilla.org</a> <span lang="zh-CN"><span>工作的</span></span> content scripts <span lang="zh-CN"><span>,但目前该网站已禁止</span></span> content scripts <span lang="zh-CN"><span>。</span></span></p>
+</div>
+
+<h2 id="消息">消息</h2>
+
+<p>内容脚本和后台脚本不能直接相互访问,但可以通过发送消息进行通信。当一端设置一个消息侦听器时,另一个端就可以发送消息了。下面的表格总结了通信时的api接口:</p>
+
+<table class=" fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="row"> </th>
+ <th scope="col">在内容脚本中</th>
+ <th scope="col">在后台脚本中</th>
+ </tr>
+ <tr>
+ <th scope="row">发送消息</th>
+ <td><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#sendMessage()">browser.runtime.sendMessage()</a></code></td>
+ <td><code><a href="/en-US/Add-ons/WebExtensions/API/Tabs/sendMessage">browser.tabs.sendMessage()</a></code></td>
+ </tr>
+ <tr>
+ <th scope="row">接收消息</th>
+ <td><code><a href="/en-US/Add-ons/WebExtensions/API/runtime/onMessage">browser.runtime.onMessage</a></code></td>
+ <td><code><a href="/en-US/Add-ons/WebExtensions/API/runtime#onMessage">browser.runtime.onMessage</a></code></td>
+ </tr>
+ </thead>
+</table>
+
+<p>修改上面的示例,使得可以通过后台脚本来发送消息。</p>
+
+<p>首先,修改 "background.js" 如下:</p>
+
+<pre class="brush: js">browser.contextMenus.create({
+ id: "eat-page",
+ title: "Eat this page"
+});
+
+function messageTab(tabs) {
+ browser.tabs.sendMessage(tabs[0].id, {
+ replacement: "Message from the add-on!"
+ });
+}
+
+browser.contextMenus.onClicked.addListener(function(info, tab) {
+ if (info.menuItemId == "eat-page") {
+ browser.tabs.executeScript({
+ file: "page-eater.js"
+ });
+
+ var querying = browser.tabs.query({
+ active: true,
+ currentWindow: true
+ });
+ querying.then(messageTab);
+ }
+});
+</pre>
+
+<p> 注入 "page-eater.js"后, 通过使用 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query">tabs.query()</a></code> 获取当前活动标签页, 然后使用<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage">tabs.sendMessage()</a></code> 将消息发送到该标签页中的内容脚本。 该消息的内容 <code>{replacement: "Message from the add-on!"}。</code></p>
+
+<p>接下来,修改 "page-eater.js" 如下:</p>
+
+<pre class="brush: js">function eatPage(request, sender, sendResponse) {
+ document.body.textContent = "";
+
+ var header = document.createElement('h1');
+ header.textContent = request.replacement;
+ document.body.appendChild(header);
+}
+
+browser.runtime.onMessage.addListener(eatPage);
+</pre>
+
+<p>现在,不再立即执行吞页,内容脚本将先通过使用 <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage">runtime.onMessage</a></code>来监听消息。当监听到消息时, 内容脚本才开始运作,除了来自<code>request.replacement</code>的替换文本不一样以外,其他的脚本运作本质上与之前的相同 。</p>
+
+<p>如果我们想将消息从内容脚本发送到后台页面,除了在内容脚本中使用 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage">runtime.sendMessage()</a></code> ,其他与上面的过程相反。</p>
+
+<div class="note">
+<p><span id="result_box" lang="zh-CN"><span>这些例子注入的都是JavaScript;</span> 想</span><span lang="zh-CN"><span>注入CSS可以使用</span></span> <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/insertCSS">tabs.insertCSS()</a></code> <span lang="zh-CN"><span>函数。</span></span></p>
+</div>
+
+<h2 id="了解更多">了解更多</h2>
+
+<ul>
+ <li><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">Content scripts</a> 指南</li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/content_scripts">content_scripts</a></code> manifest key</li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code> manifest key</li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript">tabs.executeScript()</a></code></li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/insertCSS">tabs.insertCSS()</a></code></li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage">tabs.sendMessage()</a></code></li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/sendMessage">runtime.sendMessage()</a></code></li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage">runtime.onMessage</a></code></li>
+ <li>使用<code>content_scripts</code>的例子:
+ <ul>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/borderify">borderify</a></li>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/inpage-toolbar-ui">inpage-toolbar-ui</a></li>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a></li>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/page-to-extension-messaging">page-to-extension-messaging</a></li>
+ </ul>
+ </li>
+ <li>使用<code>tabs.executeScript()</code>的例子:
+ <ul>
+ <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/beastify">beastify</a></li>
+ <li><a class="external external-icon" href="https://github.com/mdn/webextensions-examples/tree/master/context-menu-demo">context-menu-demo</a></li>
+ </ul>
+ </li>
+</ul>
+
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/native_manifests/index.html b/files/zh-cn/mozilla/add-ons/webextensions/native_manifests/index.html
new file mode 100644
index 0000000000..b83609fa85
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/native_manifests/index.html
@@ -0,0 +1,344 @@
+---
+title: 原生应用清单
+slug: Mozilla/Add-ons/WebExtensions/Native_manifests
+translation_of: Mozilla/Add-ons/WebExtensions/Native_manifests
+---
+<div>{{AddonSidebar}}</div>
+
+<p> </p>
+
+<p>原生应用清单是一个符合特定规则的JSON文件,它应该使用与 extension 不同的安装方式存放在用户的计算机上。举个例子,原生应用清单是由设备管理员或者通过原生应用安装器提供的。</p>
+
+<p>有三种不同的原生应用清单:</p>
+
+<table class="standard-table">
+ <tbody>
+ <tr>
+ <td style="width: 40%;"><a href="#原生应用通信清单">原生应用通信清单</a></td>
+ <td>
+ <p>定义关于 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Native_messaging">与本地应用通信</a> 的功能:哪一个 extension 可以与本机的原生应用交换信息。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><a href="#存储管理清单">存储管理清单</a></td>
+ <td>
+ <p>定义一些 extension 可以用 {{WebExtAPIRef("storage.managed")}} 读取的只读数据。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><a href="#PKCS #11 清单">PKCS #11 清单</a></td>
+ <td>
+ <p>定义了 extension 使用 {{WebExtAPIRef("pkcs11")}} API 去枚举 PKCS #11 安全模型 并在Firefox安装它们。</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>对于所有的原生应用清单,你需要做一些工作以便于浏览器可以找到它们。这些规则在 <a href="#清单路径">清单路径</a><a href="#Manifest_location"> </a>章节。</p>
+
+<h2 id="原生应用通信清单_2">原生应用通信清单<a id="原生应用通信清单" name="原生应用通信清单"></a></h2>
+
+<p>原生应用通信清单中包含单个JSON对象,对象具有如下属性:</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col">Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>name</code></td>
+ <td>String</td>
+ <td>
+ <p>原生应用的名字</p>
+
+ <p>它必须与 extension 调用 {{WebExtAPIRef("runtime.connectNative()")}} 和 {{WebExtAPIRef("runtime.sendNativeMessage()")}} 时传入的名称保持一致。</p>
+
+ <p>在 OS X 和 Linux 中,它必须和清单文件的文件名保持一致(除.json文件扩展名外)。</p>
+
+ <p>在 Windows 中,它必须和你创建的包含原生应用清单路径的注册表一致。</p>
+
+ <p>它必须符合正则表达式  "^\w+(\.\w+)*$"。这意味着它只能包含小写字母、数字、下划线和 <code>.</code> ,并且不允许开头或结束是 <code>.</code> ,并且 <code>.</code> 后面不能是 <code>.</code> 。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>description</code></td>
+ <td>String</td>
+ <td>
+ <p>关于这个原生应用的描述。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>path</code></td>
+ <td>String</td>
+ <td>
+ <p>到原生应用的路径。</p>
+
+ <p>在 Windows 中,这可以是一个相对路径。在 OS X 和 Linux 中,必须是绝对路径。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>type</code></td>
+ <td>String</td>
+ <td>
+ <p>定义 extension 和原生应用的连接方法。</p>
+
+ <p>目前只支持一种值,那就是 stdio。该值表示应用使用标准输入(stdin)来接受消息,用标准输出(stdout)来发送消息。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>allowed_extensions</code></td>
+ <td>Array of String</td>
+ <td>
+ <p>由 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID">Add-on ID</a> 组成的数组。每个值代表允许ID为该值的 extension 与这个原生应用通信。</p>
+
+ <div class="note">
+ <p>这意味着你可能需要在你 extension 的 manifest.json 中包含 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications">applications</a> 字段,并为 extension 设置一个显示的ID,哪怕是在开发时</p>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>举个例子,这是 ping_pong 原生应用的原生应用通信清单:</p>
+
+<pre class="brush: json">{
+ "name": "ping_pong",
+ "description": "Example host for native messaging",
+ "path": "/path/to/native-messaging/app/ping_pong.py",
+ "type": "stdio",
+ "allowed_extensions": [ "ping_pong@example.org" ]
+}</pre>
+
+<p>清单表示:它允许ID为 ping_pong@example.org 的 extension 通过传入 ping_pong 给 {{WebExtAPIRef("runtime")}} 与自己连接。原生应用自身在 /path/to/native-messaging/app/ping_pong.py 中。</p>
+
+<h2 id="存储管理清单_2">存储管理清单<a id="存储管理清单" name="存储管理清单"></a></h2>
+
+<p>存储管理清单中包含单个JSON对象,对象具有如下属性:</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col">Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>name</code></td>
+ <td>String</td>
+ <td>
+ <p><strong>一个</strong> extension 的 ID,表示这个 extension 可以读取这个仓库。</p>
+
+ <p>给出这个ID需要你的 extension 的 manifest.json 文件包含 <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications">applications</a> 字段。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>description</code></td>
+ <td>String</td>
+ <td>
+ <p>人类可读的描述,Firefox会忽略它。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>type</code></td>
+ <td>String</td>
+ <td>
+ <p>该值只能是<code>storage</code>。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>data</code></td>
+ <td>Object</td>
+ <td>
+ <p>一个JSON对象,其中可以包含任何合法的JSON值(string、number、boolean、array、object),他们将成为<code>browser.storage.managed</code>可访问的数据。</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>举个例子:</p>
+
+<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="punctuation token">{</span>
+ <span class="key token">"name":</span> <span class="string token">"favourite-colour-examples@mozilla.org"</span><span class="punctuation token">,</span>
+ <span class="key token">"description":</span> <span class="string token">"ignored"</span><span class="punctuation token">,</span>
+ <span class="key token">"type":</span> <span class="string token">"storage"</span><span class="punctuation token">,</span>
+ <span class="key token">"data":</span>
+ <span class="punctuation token">{</span>
+ <span class="key token">"colour":</span> <span class="string token">"management thinks it should be blue!"</span>
+ <span class="punctuation token">}</span>
+<span class="punctuation token">}</span></code></pre>
+
+<p>在给出的清单文件中,ID 为 favourite-colour-examples@mozilla.org 的 extension 有权限使用清单中的 data 字段中的数据,代码如下:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> storageItem <span class="operator token">=</span> browser<span class="punctuation token">.</span>storage<span class="punctuation token">.</span>managed<span class="punctuation token">.</span><span class="keyword token">get</span><span class="punctuation token">(</span><span class="string token">'colour'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+storageItem<span class="punctuation token">.</span><span class="function token">then</span><span class="punctuation token">(</span><span class="punctuation token">(</span>res<span class="punctuation token">)</span> <span class="operator token">=</span><span class="operator token">&gt;</span> <span class="punctuation token">{</span>
+ console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span><span class="template-string token"><span class="string token">`Managed colour is: </span><span class="interpolation token"><span class="interpolation-punctuation punctuation token">${</span>res<span class="punctuation token">.</span>colour<span class="interpolation-punctuation punctuation token">}</span></span><span class="string token">`</span></span><span class="punctuation token">)</span><span class="punctuation token">;</span>
+<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<h2 id="PKCS_11_清单">PKCS #11 清单<a id="PKCS #11 清单" name="PKCS #11 清单"></a></h2>
+
+<p>PKCS #11 清单中包含单个JSON对象,对象具有如下属性:</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Name</th>
+ <th scope="col">Type</th>
+ <th scope="col">Description</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code>name</code></td>
+ <td>String</td>
+ <td>
+ <p>PKCS #11 模块的名字。</p>
+
+ <p>它必须和你使用 <code>pkcs11</code> API 时的名字一致。</p>
+
+ <p>在 OS X 和 Linux 中,它必须和清单文件的文件名保持一致(除文件扩展名外)</p>
+
+ <p>在 Windows 中,它必须和你创建的包含原生应用清单路径的注册表一致。</p>
+
+ <p>它必须符合正则表达式  "^\w+(\.\w+)*$"。这意味着它只能包含小写字母、数字、下划线和 <code>.</code> ,并且不允许开头或结束是 <code>.</code> ,并且 <code>.</code> 后面不能是 <code>.</code> 。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>description</code></td>
+ <td>String</td>
+ <td>
+ <p>关于该模块的描述。</p>
+
+ <p>它将被用在浏览器界面中为模块设置一个友好的名字(比如,在Firefox的“安全设备”对话框中)</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>path</code></td>
+ <td>String</td>
+ <td>
+ <p>到模块的路径。</p>
+
+ <p>在 Windows 中,这可以是一个相对路径。在 OS X 和 Linux 中,必须是绝对路径。</p>
+ </td>
+ </tr>
+ <tr>
+ <td><code>type</code></td>
+ <td>String</td>
+ <td>该值只能是<code>pkcs11</code>。 This must be "pkcs11".</td>
+ </tr>
+ <tr>
+ <td><code>allowed_extensions</code></td>
+ <td>Array of String</td>
+ <td>
+ <p>由 <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID">Add-on ID</a> 组成的数组。每个值代表允许ID为该值的 extension 与这个模块通信。</p>
+
+ <div class="note">
+ <p>这意味着你可能需要在你 extension 的 manifest.json 中包含 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications">applications</a> 字段,并为 extension 设置一个显示的ID,哪怕是在开发时</p>
+ </div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p>举个例子:</p>
+
+<pre class="brush: json line-numbers language-json">{
+  "name": "my_module",
+  "description": "My test module",
+  "type": "pkcs11",
+  "path": "/path/to/libpkcs11testmodule.dylib",
+  "allowed_extensions": ["my-extension@mozilla.org"]
+}</pre>
+
+<p>给出的这个JSON清单,保存为 my_module.json,ID为 my-extension@mozilla.org 的 extension 就能够使用类似于如下代码安装 /path/to/libpkcs11testmodule.dylib 安全模块:</p>
+
+<pre class="brush: js line-numbers language-js">browser.pkcs11.installModule("my_module");</pre>
+
+<h2 id="清单路径_2">清单路径<a id="清单路径" name="清单路径"></a></h2>
+
+<p>在 Linux 和 Mac OS X 中,你需要将清单文件存在特定的位置。在 Windows 中,你需要创建一个注册表来指向清单文件。</p>
+
+<p>所有类型的清单的详细规则都是相同的,除了倒数第二个的 type 字段表示了清单的类型。下面的例子展示了三种不同类型的清单。在例子中,&lt;name&gt; 代表清单中的 name 字段值。</p>
+
+<h3 id="Windows">Windows</h3>
+
+<p>如果想要全局可见,使用下面的路径创建注册表:</p>
+
+<pre>HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\NativeMessagingHosts\&lt;name&gt;
+
+HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\<code class="language-html">ManagedStorage</code>\&lt;name&gt;
+
+HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\PKCS11Modules\&lt;name&gt;</pre>
+
+<p>注册表应该有单个默认值,值里存放“到清单文件的路径”。比如为原生应用通信清单建立的注册表差不多是这样:</p>
+
+<p><img alt="为原生应用通信清单建立的注册表" src="https://mdn.mozillademos.org/files/15643/native-message-regkey-exaple.png" style="height: 308px; width: 1027px;"></p>
+
+<div class="note">
+<p><em>对于原生应用清单,即使原生应用是32位的,也不能在 <a href="https://en.wikipedia.org/wiki/WoW64#Registry_and_file_system">Wow6432Node</a> 下创建注册表。浏览器将总会在 native 视图下寻找注册表的,而不是32位放在环境。确保注册表的创建在原生视图中,你可以键入KEY_WOW64_64KEY 或 KEY_WOW64_32KEY  到 RegCreateKeyEx。请参考:<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa384129(v=vs.85).aspx">Accessing an Alternate Registry View</a></em></p>
+</div>
+
+<p>如果想要用户级别的可见,使用下面的路径创建注册表:</p>
+
+<pre>HKEY_CURRENT_USER\SOFTWARE\Mozilla\NativeMessagingHosts\&lt;name&gt;
+
+HKEY_CURRENT_USER\SOFTWARE\Mozilla\<code class="language-html">ManagedStorage</code>\&lt;name&gt;
+
+HKEY_CURRENT_USER\SOFTWARE\Mozilla\PKCS11Modules\&lt;name&gt;</pre>
+
+<p>注册表应该有单个默认值,值里存放“到清单文件的路径”。</p>
+
+<h3 id="Mac_OS_X">Mac OS X</h3>
+
+<p>如果想要全局可见,将清单文件存放在:</p>
+
+<pre>/Library/Application Support/Mozilla/NativeMessagingHosts/&lt;name&gt;.json
+
+/Library/Application Support/Mozilla/<code class="language-html">ManagedStorage</code>/&lt;name&gt;.json
+
+/Library/Application Support/Mozilla/PKCS11Modules/&lt;name&gt;.json</pre>
+
+<p>如果想要用户级别的可见,将清单文件存放在:</p>
+
+<pre>~/Library/Application Support/Mozilla/NativeMessagingHosts/&lt;name&gt;.json
+
+~/Library/Application Support/Mozilla/<code class="language-html">ManagedStorage</code>/&lt;name&gt;.json
+
+~/Library/Application Support/Mozilla/PKCS11Modules/&lt;name&gt;.json
+</pre>
+
+<h3 id="Linux">Linux</h3>
+
+<p>如果想要全局可见,将清单文件存放在:</p>
+
+<pre>/usr/lib/mozilla/native-messaging-hosts/&lt;name&gt;.json
+
+/usr/lib/mozilla/<code class="language-html">managed-storage</code>/&lt;name&gt;.json
+
+/usr/lib/mozilla/pkcs11-modules/&lt;name&gt;.json
+</pre>
+
+<p>或者:</p>
+
+<pre>/usr/lib64/mozilla/native-messaging-hosts/&lt;name&gt;.json
+
+/usr/lib64/mozilla/<code class="language-html">managed-storage</code>/&lt;name&gt;.json
+
+/usr/lib64/mozilla/pkcs11-modules/&lt;name&gt;.json</pre>
+
+<p>如果想要用户级别的可见,将清单文件存放在:</p>
+
+<pre>~/.mozilla/native-messaging-hosts/&lt;name&gt;.json
+
+~/.mozilla/<code class="language-html">managed-storage</code>/&lt;name&gt;.json
+
+~/.mozilla/pkcs11-modules/&lt;name&gt;.json</pre>
+
+<p> </p>
+
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/native_messaging/index.html b/files/zh-cn/mozilla/add-ons/webextensions/native_messaging/index.html
new file mode 100644
index 0000000000..505ba9a16a
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/native_messaging/index.html
@@ -0,0 +1,326 @@
+---
+title: 与本地应用通信
+slug: Mozilla/Add-ons/WebExtensions/Native_messaging
+translation_of: Mozilla/Add-ons/WebExtensions/Native_messaging
+---
+<div>{{AddonSidebar}}</div>
+
+<p>Native messaging 可以让 extension 与安装在用户计算机上的原生应用交换信息。 原生应用仅需给 extension 提供服务,而无需在网页中可访问。 一个常见的例子是密码管理器: 原生应用负责存储和加密你的密码,并且和 extension 通信来填充网页中的表单字段。Native messaging 可以让 extension 拥有那些WebExtensions APIs 所没有的功能,比如访问某些特定的硬件。</p>
+
+<p>原生应用的安装与管理并不是在浏览器当中的: 它应该是使用操作系统进行安装,和其他的原生应用一样。然后你需要将你的原生应用安装在指定位置,并提供一个清单。清单中描述了浏览器如何连接到你的原生应用。</p>
+
+<p>extension 必须在 manifest.json 中获得"nativeMessaging" <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a>。 同时,原生应用也需要在其清单中的 "allowed_extensions" 字段中包含 extension 的ID来表示允许该 extension 与自己进行通信。</p>
+
+<p>经过上述操作,extension 就可以通过 {{WebExtAPIRef("runtime")}} API 与原生应用进行JSON数据通信了。原生应用可以通过标准输入/输出来接受/返回数据与 extension 通信。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/13833/native-messaging.png" style="display: block; height: 548px; margin-left: auto; margin-right: auto; width: 672px;"></p>
+
+<p>和 Chrome 相比,WebExtensions 所支持的 native messaging 有2个主要区别:</p>
+
+<ul>
+ <li>在 WebExtensions 中,原生应用的清单中的 "allowed_extensions" 字段是一个由 extension ID 组成的数组,而在 Chrome 中,清单中的 "allowed_origins" 字段是一个由 "chrome-extension" URLs 组成的数组</li>
+ <li>原生应用清单的存储位置不一样</li>
+</ul>
+
+<p>Github 中的 <a href="https://github.com/mdn/webextensions-examples">webextensions-examples 仓库</a>有一个<a href="https://github.com/mdn/webextensions-examples/tree/master/native-messaging">完整的关于 native messaging 的例子</a>,文章中的大部分代码片段均出于此。</p>
+
+<h2 id="安装">安装</h2>
+
+<h3 id="Extension_的_manifest.json">Extension 的 manifest.json</h3>
+
+<p>如果你想让你的 extension 与原生应用进行通信,你需要:</p>
+
+<ul>
+ <li>你必须在 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> 中申请 "nativeMessaging" 的 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">权限</a> 。</li>
+ <li>你可能需要明确自己 extension 的ID(因为在原生应用的清单中,extension ID将会在被用来识别此 extension 是否被允许与原生应用通信)</li>
+</ul>
+
+<p>这有一个 manifest.json 的例子:</p>
+
+<pre class="brush: json">{
+
+ "description": "Native messaging example extension",
+ "manifest_version": 2,
+ "name": "Native messaging example",
+ "version": "1.0",
+ "icons": {
+ "48": "icons/message.svg"
+ },
+
+ "applications": {
+ "gecko": {
+ "id": "ping_pong@example.org",
+ "strict_min_version": "50.0"
+ }
+ },
+
+ "background": {
+ "scripts": ["background.js"]
+ },
+
+ "browser_action": {
+ "default_icon": "icons/message.svg"
+ },
+
+ "permissions": ["nativeMessaging"]
+
+}</pre>
+
+<h3 id="原生应用清单">原生应用清单</h3>
+
+<p>原生应用清单描述了浏览器如何与原生应用进行连接。</p>
+
+<p>原生应用清单需要与原生应用一起安装,浏览器仅会查阅清单而不会安装或管理原生应用。因此,何时采用何种方式来安装或更新这些文件的安全模型比起使用WebExtensions APIs 更像原生应用 。(我也搞不懂这句啥意思,原文:Thus the security model for when and how these files are installed and updated is much more like that for native applications than that for extensions using WebExtension APIs.)</p>
+
+<p>关于原生应用清单的详细语法和路径规则,可参考 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests">原生应用清单</a>。</p>
+
+<blockquote>
+<div class="warning">
+<p>除清单外,原生应用还<strong>必需</strong>配置路径规则,你可以参考 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests">原生应用清单 </a>来配置路径。</p>
+</div>
+</blockquote>
+
+<p>这有一个例子,是关于 "ping_pong" 原生应用的清单:</p>
+
+<pre class="brush: json">{
+ "name": "ping_pong",
+ "description": "Example host for native messaging",
+ "path": "/path/to/native-messaging/app/ping_pong.py",
+ "type": "stdio",
+ "allowed_extensions": [ "ping_pong@example.org" ]
+}</pre>
+
+<p>上面的清单代表:</p>
+
+<ul>
+ <li>这个原生应用允许ID为 "ping_pong@example.org" 的 extension 连接,并通过{{WebExtAPIRef("runtime")}} API来传入信息</li>
+ <li>这个原生应用本身存放在本机的 "/path/to/native-messaging/app/ping_pong.py" 中</li>
+</ul>
+
+<div class="note">
+<p><strong>对于Windows</strong>: 在上面的例子中,原生应用是一个Python脚本,它在Windows下可能是无法运行的。一个代替方案是提供一个 .bat 文件,并且在清单中指向这个 .bat 文件:</p>
+
+<pre class="brush: json">{
+ "name": "ping_pong",
+ "description": "Example host for native messaging",
+ "path": "c:\\path\\to\\native-messaging\\app\\ping_pong_win.bat",
+ "type": "stdio",
+ "allowed_extensions": [ "ping_pong@example.org" ]
+}</pre>
+
+<p>在 .bat 文件中调用 Python 脚本:</p>
+
+<pre class="brush: bash">@echo off
+
+python -u "c:\\path\\to\\native-messaging\\app\\ping_pong.py"</pre>
+
+<p> </p>
+</div>
+
+<ul>
+</ul>
+
+<h2 id="交换信息">交换信息</h2>
+
+<p>根据上面的配置,extension已经可以和原生应用交换JSON信息了。</p>
+
+<h3 id="Extension_端">Extension 端</h3>
+
+<p>你使用过 <a href="/zh-CN/Add-ons/WebExtensions/Content_scripts#Communicating_with_background_scripts">messaging APIs</a> 与 content script 通信,与原生应用通信你应该非常熟悉,有2种方式:</p>
+
+<ul>
+ <li>基于连接的通信</li>
+ <li>无连接的通信(请求/响应 模式)</li>
+</ul>
+
+<h4 id="基于连接的通信">基于连接的通信</h4>
+
+<p>在这种方式下,你需要调用 {{WebExtAPIRef("runtime.connectNative()")}} 并传入原生应用的名称(名称在原生应用清单中的 "name" 字段定义)。这个操作将会运行原生应用(如果它之前没在运行的话)并返回一个 {{WebExtAPIRef("runtime.Port")}} 。</p>
+
+<p>当原生应用启动后,它被会传入2个参数:</p>
+
+<ul>
+ <li>到原生应用清单的完整路径</li>
+ <li>(Firefox 55+)启动它的<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications"> extension ID</a></li>
+</ul>
+
+<p>原生应用会一直保持运行,直到 extension 调用 <code>Port.disconnect()</code> 或连接它的记录被结束。</p>
+
+<p>使用 <code>Port</code> ,调用 <code>postMessage()</code> 传入一个JSON来发送消息,使用 <code>onMessage.addListener()</code> 来接收消息。</p>
+
+<p>下面是一个例子:background script 建立与 ping_pong 原生应用的链接,并监听原生应用发来的消息。每当browser action 点击时,发送一个 ping 的消息给原生应用。</p>
+
+<pre class="brush: js">/*
+启动,连接 ping_pong 原生应用
+*/
+var port = browser.runtime.connectNative("ping_pong");
+
+/*
+监听从原生应用发来的消息
+*/
+port.onMessage.addListener((response) =&gt; {
+ console.log("Received: " + response);
+});
+
+/*
+每当 browser action 被点击时,发送一条消息给原生应用
+*/
+browser.browserAction.onClicked.addListener(() =&gt; {
+ console.log("Sending: ping");
+ port.postMessage("ping");
+});</pre>
+
+<h4 id="无连接的通信">无连接的通信</h4>
+
+<p>在这种模式下你需要调用 {{WebExtAPIRef("runtime.sendNativeMessage()")}} 传入如下参数:</p>
+
+<ul>
+ <li>原生应用的名字</li>
+ <li>要发送是JSON数据</li>
+ <li>(可选)一个回调函数</li>
+</ul>
+
+<p>每个消息都会创建一个新的原生应用实例。当原生应用启动时会被传入2个参数:</p>
+
+<ul>
+ <li>到原生应用清单的完整路径</li>
+ <li>(Firefox 55+)启动它的<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications"> extension ID</a></li>
+</ul>
+
+<p>原生应用发送的第一条消息将会被作为对 <code>sendNativeMessage()</code> 响应,将会被传入回调函数中。</p>
+
+<p>这有一个例子,对在上方的代码片段进行重写,改成使用 <code>runtime.sendNativeMessage()</code> 的方式:</p>
+
+<pre class="brush: js">function onResponse(response) {
+ console.log("Received " + response);
+}
+
+function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+/*
+每当 browser action 被点击时,发送一条消息给原生应用
+*/
+browser.browserAction.onClicked.addListener(() =&gt; {
+ console.log("Sending: ping");
+ var sending = browser.runtime.sendNativeMessage(
+ "ping_pong",
+ "ping");
+ sending.then(onResponse, onError);
+});
+</pre>
+
+<h3 id="原生应用端">原生应用端</h3>
+
+<p>在原生应用端,使用标准输入来接受消息,使用标准输出来发送消息。</p>
+
+<p>每条消息将会被序列化成UTF-8格式的JSON数据,并且在消息前面有一个32位的值来表示该条消息使用本地字节序的长度。</p>
+
+<p>发送给原生应用的单条消息最大是1MB,总消息不得超越4GB。</p>
+
+<p>下面是一个用 Python 写的原生应用例子。监听 extensions 发送的消息,如果消息是 ping,则回复 pong:</p>
+
+<pre class="brush: python">#!/usr/bin/python -u
+# Note that running python with the `-u` flag is required on Windows,
+# in order to ensure that stdin and stdout are opened in binary, rather
+# than text, mode.
+
+import sys, json, struct
+
+# 从 stdin 读取解码消息
+def getMessage():
+ rawLength = sys.stdin.read(4)
+ if len(rawLength) == 0:
+ sys.exit(0)
+ messageLength = struct.unpack('@I', rawLength)[0]
+ message = sys.stdin.read(messageLength)
+ return json.loads(message)
+
+# 为了能被传输,对给定的内容进行编码
+def encodeMessage(messageContent):
+ encodedContent = json.dumps(messageContent)
+ encodedLength = struct.pack('@I', len(encodedContent))
+ return {'length': encodedLength, 'content': encodedContent}
+
+# 向 stdout 发送一个已编码的消息
+def sendMessage(encodedMessage):
+ sys.stdout.write(encodedMessage['length'])
+ sys.stdout.write(encodedMessage['content'])
+ sys.stdout.flush()
+
+while True:
+ receivedMessage = getMessage()
+ if (receivedMessage == "ping"):
+ sendMessage(encodeMessage("pong"))
+</pre>
+
+<h2 id="关闭原生应用">关闭原生应用</h2>
+
+<p>如果你通过 <code>runtime.connectNative()</code> 连接原生应用,则原生应用会一直保持运行,直到 extension 调用 <code>Port.disconnect()</code> 或连接它的记录被结束。 如果你通过 <code>runtime.sendNativeMessage()</code> 向原生应用发消息,原生应用会在回复消息后被关闭。</p>
+
+<p>关闭原生应用的过程:</p>
+
+<ul>
+ <li>在 *nix 系统比如 OS X 和Linux 中,浏览器会向原生应用发送 SIGTERM 信号让其可以优雅的退出,然后再发送 SIGKILL 信号。这些信号将会传递给每一个子进程,除非它们分裂成一个新的进程组。</li>
+ <li>在 Windows 中,浏览器会向原生应用的进程发送一个 <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms684161(v=vs.85).aspx">Job object</a> 并杀死任务,如果原生应用启动任何的额外进程并希望它们能在原生应用被杀死后继续保持运行,原生应用需要在启动进程时使用 <code><a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863(v=vs.85).aspx">CREATE_BREAKAWAY_FROM_JOB</a></code> 标记。</li>
+</ul>
+
+<h2 id="常见问题_Troubleshooting">常见问题 Troubleshooting</h2>
+
+<p>如果有什么地方出错,可以检查<a href="/en-US/Add-ons/WebExtensions/Debugging#Viewing_log_output">浏览器控制台</a>。原生应用发送的任何 stderr 都会被反应在浏览器控制台中。所以如果你已经运行了原生应用,你可以看到原生应用发出的所有错误信息。</p>
+
+<p>如果你没有配置好原生应用,你应该会看到一些错误信息。</p>
+
+<pre>"No such native application &lt;name&gt;"</pre>
+
+<ul>
+ <li>检查 <code>runtime.connectNative()</code> 传入的名称与应用程序清单中的名称一致</li>
+ <li>OS X/Linux:检查原生应用清单文件的名称是 &lt;name&gt;.json</li>
+ <li>Windows:检查注册表是否在正确的位置,并且它的名称是否与应用程序清单中的名称一致</li>
+ <li>Windows:检查注册中给出的路径是否指向的是原生应用清单</li>
+</ul>
+
+<pre>"Error: Invalid application &lt;name&gt;"</pre>
+
+<ul>
+ <li>检查原生应用的名称是否有非法字符</li>
+</ul>
+
+<pre>"'python' is not recognized as an internal or external command, ..."</pre>
+
+<ul>
+ <li>Windows:如果你的应用是一个Python script,检查你是否已经安装过Python,并为其配置好路径</li>
+</ul>
+
+<pre>"File at path &lt;path&gt; does not exist, or is not executable"</pre>
+
+<ul>
+ <li>如果你看见它,意味着应用程序清单已经被找到了</li>
+ <li>检查应用程序清单的 path 字段是正确的</li>
+ <li>Windows:检查你是否已经转移过了路径分隔符 ("c:\\path\\to\\file")</li>
+ <li>检查原生应用是否在原生应用清单中的 path 字段中指向的本地路径</li>
+ <li>检查原生应用是否可执行</li>
+</ul>
+
+<pre>"This extension does not have permission to use native application &lt;name&gt;"</pre>
+
+<ul>
+ <li>检查原生应用清单中的 "allowed_extensions" 字段中是否包含了 extension 的 ID。</li>
+</ul>
+
+<pre>"TypeError: browser.runtime.connectNative is not a function"</pre>
+
+<ul>
+ <li>检查 extension 是否已经拥有了 nativeMessaging 权限</li>
+</ul>
+
+<pre>"[object Object] NativeMessaging.jsm:218"</pre>
+
+<ul>
+ <li>这是一个启动原生应用时的问题。</li>
+</ul>
+
+<h2 id="与_Chrome_的兼容问题">与 Chrome 的兼容问题</h2>
+
+<p>{{Page("Mozilla/Add-ons/WebExtensions/Chrome_incompatibilities", "Native_messaging")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/packaging_and_installation/index.html b/files/zh-cn/mozilla/add-ons/webextensions/packaging_and_installation/index.html
new file mode 100644
index 0000000000..e0eb081cc7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/packaging_and_installation/index.html
@@ -0,0 +1,82 @@
+---
+title: 打包和安装
+slug: Mozilla/Add-ons/WebExtensions/Packaging_and_installation
+translation_of: Mozilla/Add-ons/WebExtensions/Temporary_Installation_in_Firefox
+---
+<h2 id="打包你的扩展">打包你的扩展</h2>
+
+<p>Firefox 扩展应打包为 XPI 文件。它只是一个 ZIP 文件,但采用 <code>.xpi</code> 作为扩展名。</p>
+
+<p>最重要的一点,ZIP 文件必须是扩展文件的 ZIP 打包,<strong>不能</strong>包含一层根目录。</p>
+
+<h3 id="Windows">Windows</h3>
+
+<ol>
+ <li>打开你的扩展文件所在的文件夹。</li>
+ <li>选择所有文件。</li>
+ <li>右击并选择 发送到 → 压缩(zipped)文件夹。</li>
+ <li>将得到的文件从 <code>文件名.zip</code> 重命名为 <code>文件名.xpi</code>。</li>
+</ol>
+
+<p><img alt="Screenshot of the Windows Explorer context menu showing Send to compressed (zipped) folder" src="https://mdn.mozillademos.org/files/11717/pUF1vnr.png" style="height: 641px; width: 904px;"></p>
+
+<h3 id="Mac_OS_X">Mac OS X</h3>
+
+<ol>
+ <li>打开你的扩展文件所在的文件夹。</li>
+ <li>选择所有文件。</li>
+ <li>右击并选择 压缩 <em>n</em> 项。</li>
+ <li>将得到的文件从 <code>Archive.zip</code> 重命名为  <code>文件名.xpi</code>。</li>
+</ol>
+
+<p><img alt="Screenshot of the Finder context menu showing the Compress 15 Items option" src="https://mdn.mozillademos.org/files/11715/Screen%20Shot%202015-10-08%20at%2016.19.02.png" style="height: 460px; width: 850px;"></p>
+
+<h3 id="Linux_Mac_OS_X_终端">Linux / Mac OS X 终端</h3>
+
+<ol>
+ <li><code>cd path/to/my-extension/</code></li>
+ <li><code>zip -r ../my-extension.xpi *</code></li>
+</ol>
+
+<h2 id="安装你的扩展">安装你的扩展</h2>
+
+<ol>
+ <li>导航到 <code>about:addons</code></li>
+ <li>拖拽 XPI 到页面上,或者打开齿轮菜单,选择“从文件安装附加组件...”</li>
+ <li>点击弹出的对话框中的“安装”</li>
+</ol>
+
+<h2 id="在_Firefox_OS_上安装你的扩展">在 Firefox OS 上安装你的扩展</h2>
+
+<p><code>你可以使用 WebIDE 提供的 USB 或者 Wifi 进行安装</code></p>
+
+<h2 id="故障排除">故障排除</h2>
+
+<p>下面是几种你可能会遇到的常见问题:</p>
+
+<h3 id="此附加组件无法安装,因为它未经验证。">"此附加组件无法安装,因为它未经验证。"</h3>
+
+<ul>
+ <li>确保你正在使用 <a href="https://nightly.mozilla.org/">Nightly</a> ,并且已在 <code>about:config </code>中将 <code>xpinstall.signatures.required</code> 切换为 <code>false</code>。</li>
+ <li>在 <a href="/en-US/docs/Mozilla/Add-ons/Distribution">附加组件签名与分发</a> 了解更多信息。</li>
+</ul>
+
+<h3 id="该附加组件无法安装,因为它似乎已损坏。">"该附加组件无法安装,因为它似乎已损坏。"</h3>
+
+<ul>
+ <li>确保你是直接压缩你的附加组件文件,<strong>而不是</strong>压缩它们所在的文件夹。你的 manifest.json 文件必须在 zip 文件的根目录中。</li>
+ <li>确保你正在使用 <a href="https://nightly.mozilla.org/">Nightly</a> 版本的 Firefox。</li>
+</ul>
+
+<h3 id="完全没反应">完全没反应</h3>
+
+<ul>
+ <li>确保你的文件名称以 <code>.xpi</code> 结尾,因为某些操作系统可能会隐藏真实的文件扩展名。
+
+ <ul>
+ <li>在 Windows 上,选中 查看 → 显示 / 隐藏:文件扩展名。</li>
+ <li>在 Mac OS X 上,选中 文件 → 获取信息 → 名称和扩展名。</li>
+ </ul>
+ </li>
+ <li>还有一种可能,你不小心点击并因此驳回了安装提示。在 Nightly 中的后退按钮旁边找到一个拼图图标。点击它将重获这个弹出提示。</li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/porting_from_google_chrome/index.html b/files/zh-cn/mozilla/add-ons/webextensions/porting_from_google_chrome/index.html
new file mode 100644
index 0000000000..496abe0bd3
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/porting_from_google_chrome/index.html
@@ -0,0 +1,22 @@
+---
+title: 从 Google Chrome 移植
+slug: Mozilla/Add-ons/WebExtensions/Porting_from_Google_Chrome
+tags:
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/Porting_a_Google_Chrome_extension
+---
+<div>{{AddonSidebar}}</div>
+
+<p>使用 WebExtension API 开发的扩展是专为跨浏览器兼容而设计的:很大程度上,该技术与 Google Chrome 和 Opera 支持的<a class="external external-icon" href="https://developer.chrome.com/extensions">扩展 API</a> 代码直接兼容。为这些浏览器编写的扩展,在大多数情况下,只需少数修改就能在 Firefox 中运行。几乎所有的<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/API">扩展 API</a> 都支持使用 <code>chrome</code> 命名空间下的回调函数,跟 Chrome 一样。那些仅有的 <code>chrome</code> 命名空间不支持的 API 是故意不与 Chrome 兼容的。这些情况下,API 文档页将明确声明它仅在 <code>browser</code> 命名空间中受支持。从 Chrome 或者 Opera 移植一个扩展的过程大概这样:</p>
+
+<ol>
+ <li>检查你 manifest.json 使用的功能并了解 WebExtension API 对应的 <a href="/en-US/Add-ons/WebExtensions/Chrome_incompatibilities">Chrome 不兼容参考表</a>。如果你在使用的功能或者 API 还未被 Firefox 支持,那你可能还不能移植你的扩展。Mozilla 提供了一个服务可助您自动执行此步:<a href="https://www.extensiontest.com/">https://www.extensiontest.com/</a>。</li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">安装你的扩展至 Firefox</a> 并对其进行测试。</li>
+ <li>如有任何问题,可通过 <a class="external external-icon" href="https://mail.mozilla.org/listinfo/dev-addons">dev-addons 邮件列表</a>或 <a class="external external-icon" href="https://wiki.mozilla.org/IRC">IRC</a> 上的 <a href="irc://irc.mozilla.org/webextensions">#webextensions</a> 联系我们。</li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Publishing_your_WebExtension">提交您的附加组件至 AMO 以供签名及分发</a>。</li>
+</ol>
+
+<p>如果您依赖 Chrome 命令行选项来加载解压的扩展,请参看 Firefox 中进行临时安装的 <a href="/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext">web-ext</a> 工具以便开发。</p>
+
+<ul>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/prerequisites/index.html b/files/zh-cn/mozilla/add-ons/webextensions/prerequisites/index.html
new file mode 100644
index 0000000000..75abcfb904
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/prerequisites/index.html
@@ -0,0 +1,21 @@
+---
+title: 前提条件
+slug: Mozilla/Add-ons/WebExtensions/Prerequisites
+tags:
+ - firefox signature config
+ - firefox webextension config
+ - xpi signatures config
+translation_of: Mozilla/Add-ons/WebExtensions/Prerequisites
+---
+<p>要使用 WebExtension API 进行开发,你需要进行一些最基本的设置。</p>
+
+<ul>
+ <li>下载、安装和启动 <a href="https://www.mozilla.org/en-US/firefox/developer/">Firefox Developer Edition</a> 或者 <a class="external text" href="https://nightly.mozilla.org/" rel="nofollow">Firefox Nightly</a>。如果想要使用最近的更新,请使用 Nightly 版本。</li>
+ <li>调整 Firefox 是否允许你安装未签名附加组件的首选项。需注意,该首选项仅在 Firefox Developer Edition 和 Firefox Nightly 中可用。
+ <ul>
+ <li>在 Firefox 的地址栏中输入 <code>about:config</code></li>
+ <li>在搜索框中输入 <code>xpinstall.signatures.required</code></li>
+ <li>双击该首选项,或者右击并选择“切换”,将其设置为 <code>false</code>。</li>
+ </ul>
+ </li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/publishing_your_webextension/index.html b/files/zh-cn/mozilla/add-ons/webextensions/publishing_your_webextension/index.html
new file mode 100644
index 0000000000..e7792b75d4
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/publishing_your_webextension/index.html
@@ -0,0 +1,98 @@
+---
+title: 发布你的附加组件
+slug: Mozilla/Add-ons/WebExtensions/Publishing_your_WebExtension
+tags:
+ - WebExtensions
+translation_of: Mozilla/Add-ons/WebExtensions/Package_your_extension_
+---
+<div>{{AddonSidebar}}</div>
+
+<p>一般当你完成了基于WebExtension技术的附加组件的代码编写和测试, 你可能会想与其他人分享这成果(不管出于什么目的...). Mozilla旗下有一个网站: <a class="external external-icon" href="https://addons.mozilla.org">addons.mozilla.org</a> (简称AMO), 开发者们可以在这里发布附加组件, 而其他用户可以在这里找到这些附加组件并安装使用, 通过在AMO上发布你的附加组件, 你可以加入到我们的社区里来, 这里有一群用户和创造者, 说不准会发现几个使用你的附加组件的人哦.</p>
+
+<p>你编写的附加组件并不一定需要发布在AMO上, 但是、即使你不打算在AMO上发布你的附加组件, 你也必须提交你的附加组件到AMO上来进行审核以获得签名。因为火狐浏览器会拒绝安装没有AMO签名的附加组件。</p>
+
+<p>所以发布一个附加组件的流程, 可概述为:</p>
+
+<ol>
+ <li>压缩你所创建的附加组件文件</li>
+ <li>在<a href="https://addons.mozilla.org/zh-CN/">AMO</a>上创建一个属于你的账户</li>
+ <li>上传你的压缩文件到AMO来进行签名和审核, 并选择是否在AMO上进行发布</li>
+ <li>修复在审核中发现的任何问题</li>
+ <li>如果你选择不在AMO上发布, 可以恢复已签名的附件组件, 并自行发布</li>
+</ol>
+
+<p>当你准备发布附加组件的新版本时, 你可以访问 <a class="external external-icon" href="https://addons.mozilla.org">addons.mozilla.org </a>的附加组件页来更新它, 并上传新的版本.<br>
+ 需要注意的是: 你必须在这个附加组件页进行更新, 否则AMO没法知道你是要更新一个已经存在的附加组件呢, 还是要上传一个全新的附加组件呢.</p>
+
+<p>如果你选择在AMO上发布你的附加组件, 之后火狐浏览器会自动检查更新. 如果你选择自行发布,  你需要在你的manifest.json中手动设置一个<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/applications">applications</a></code> 唯一标识, 并且需要手动设置<code>update_url属性指向你的</code><a href="/en-US/Add-ons/Updates">update manifest file</a>.</p>
+
+<div class="pull-aside">
+<div class="moreinfo">
+<p>火狐浏览器把附加组件包的后缀叫做或改为".xpi", 这只是".zip"的一个扩展.</p>
+
+<p>在上传附加组件到AMO的时候, 你不需要把压缩包的后缀改为".XPI".</p>
+</div>
+</div>
+
+<h2 id="1._使用zip压缩你的附加组件文件">1. 使用zip压缩你的附加组件文件</h2>
+
+<p>首先你的附加组件文件夹应该包含一个manifest.json和其他一些需要的文件 - javascript文件, icons文件, HTML文件等等. 你需要使用zip把它们压缩成一个文件以便上传到AMO.</p>
+
+<p>注意: 请将你的附加组件目录的的所有文件压缩为zip包,而 不要直接对附加组件根目录进行压缩(见下图所示).</p>
+
+<h3 id="Windows">Windows</h3>
+
+<ol>
+ <li>打开你的附加组件所在的文件夹.</li>
+ <li>选中所有文件.</li>
+ <li>右键并选择发送到 → 压缩到(zipped)文件夹.</li>
+</ol>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/11949/install-windows.png" style="display: block; height: 576px; margin-left: auto; margin-right: auto; width: 800px;"></p>
+
+<h3 id="Mac_OS_X">Mac OS X</h3>
+
+<ol>
+ <li>打开你的附加组件所在的文件夹.</li>
+ <li>选中所有文件.</li>
+ <li>右键并选择压缩<em>n项</em>.</li>
+</ol>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/11951/install-osx.png" style="display: block; height: 449px; margin-left: auto; margin-right: auto; width: 800px;"></p>
+
+<h3 id="Linux_Mac_OS_X_Terminal">Linux / Mac OS X Terminal</h3>
+
+<ol>
+ <li><code>cd path/to/my-addon/</code></li>
+ <li><code>zip -r ../my-addon.zip *</code></li>
+</ol>
+
+<h2 id="2._在AMO上创建一个账户">2. 在AMO上创建一个账户</h2>
+
+<p>访问<a href="https://addons.mozilla.org/">https://addons.mozilla.org/</a>. 如果你已经有一个<a href="https://support.mozilla.org/zh-CN/kb/firefox-mozilla">火狐账户</a>, 你可以直接使用它来登录. 否则, 点击"注册"并按要求创建一个火狐账户.</p>
+
+<h2 id="3._上传你的zip压缩文件">3. 上传你的zip压缩文件</h2>
+
+<p>接下来, 上传压缩后的附加组件到AMO进行签名和审查, 并选择是否发布到AMO, 更多细节, 可查看<a href="/en-US/Add-ons/Distribution#Submitting_to_AMO">Submitting to AMO</a>.</p>
+
+<div class="note">
+<p>需要注意的是一旦你上传了你的附加组件(基于WebExtension技术)到AMO, 你不能使用Add-on SDK或过时的XUL/XPCOM技术来更新该附加组件. 如果你切换到了这些技术平台之一, 必须把它做为新的附加组件并重新提交.</p>
+
+<p>总而言之: 像Add-on SDK和XUL/XPCOM等过时的技术体系在不久的将来都将被淘汰, WebExtensions才是唯一.</p>
+
+<p>在上传你的附加组件之前,请再次检查你的zip包内没有包含其他不相关的文件.</p>
+</div>
+
+<h2 id="4._修复审查中出现的问题">4. 修复审查中出现的问题</h2>
+
+<p>当你上传了附加组件, AMO服务器将运行一些基本的检查并立即通知你有关的一切问题. 这些问题分为2种类型: "错误"和"警告". 如果你有错误, 你必须修复它们并重新提交, 如果只是警告, 你最好也搞定它们(当可以也忽略警告): 然后可以继续提交.</p>
+
+<p>如果自动检查器没有报告任何错误, 该附件组件将进行更为详细的审核(复查). 你同样会收到审查结果并且需要修复所有问题, 然后重新提交.</p>
+
+<h2 id="5._发布你的附加组件">5. 发布你的附加组件</h2>
+
+<p>如果你选择了在AMO上托管你的附加组件, 这意味着发布过程的结束. AMO会对该附加组件进行签名和发布, 之后其他用户就能下载并安装使用了.</p>
+
+<p>如果你选择不在AMO上进行发布, 可以恢复已签名的附加组件, 并自行发布(比如把附件组件的压缩包直接发给别人).</p>
+
+<p> </p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/safely_inserting_external_content_into_a_page/index.html b/files/zh-cn/mozilla/add-ons/webextensions/safely_inserting_external_content_into_a_page/index.html
new file mode 100644
index 0000000000..d40d36d813
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/safely_inserting_external_content_into_a_page/index.html
@@ -0,0 +1,102 @@
+---
+title: Safely inserting external content into a page
+slug: Mozilla/Add-ons/WebExtensions/Safely_inserting_external_content_into_a_page
+translation_of: Mozilla/Add-ons/WebExtensions/Safely_inserting_external_content_into_a_page
+---
+<p>{{AddonSidebar}}</p>
+
+<p>很多时候你需要从外部资源引入内容到你的插件。但是,源可能被嵌入了恶意的源代码,这些恶意的源代码可能由源的开发者或者恶意的第三方所编写。</p>
+
+<p>以RSS读取器为例子。你不知道你的插件将会打开什么RSS源也无法控制那些RSS源的内容。所以,可能用户可能订阅到一个RSS源里面包含了带有恶意脚本的标题。可能就是简单的JavaScript代码标签&lt;script&gt;&lt;/script&gt;。如果你在提取标题的时候,当作一般文本添加到一个页面的DOM,用户可能加载未知的脚本。因此,需要注意避免直接把一般文本加载为HTML。</p>
+
+<p>你还需要记住扩展有授权的上下文,例如后台的脚本backgroup scrips以及内容脚本content scripts。最坏的情况里,一个内嵌的洁白你可能运行在一个或多种上下文中,导致一些提取操作。这种情况会导致用户的浏览器暴露在远程攻击下,被注入代码访问用户的重要数据,例如密码、浏览器历史或者浏览器行为等。</p>
+
+<p>这篇文章说明如何安全的对待远端数据并添加到DOM。</p>
+
+
+
+<h2 id="处理任意字符串">处理任意字符串</h2>
+
+<p>当处理字符串时,有很多推荐的策略来安全添加他们到页面:标准的DOM节点创建方法或jQuery。</p>
+
+<h3 id="DOM节点创建方法函数">DOM节点创建方法/函数</h3>
+
+<p>一个轻量级的方法来插入字符串到页面是使用原生的DOM操纵方法/函数: <a href="/en-US/docs/Web/API/Document/createElement"><code>document.createElement</code></a>, <a href="/en-US/docs/Web/API/Element/setAttribute"><code>Element.setAttribute</code></a>, 以及<a href="/en-US/docs/Web/API/Node/textContent"><code>Node.textContent</code></a>. 安全的方法是分别创建节点并使用textContent属性赋值:</p>
+
+<pre class="brush: js example-good">var data = JSON.parse(responseText);
+var div = document.createElement("div");
+div.className = data.className;
+div.textContent = "Your favorite color is now " + data.color;
+addonElement.appendChild(div);</pre>
+
+<p>这种方法安全原因是使用<code>.textContent</code> 时会自动消除 <code>data.color</code>.中的任何远程 HTML代码。</p>
+
+<p>但是要注意,使用原生方法不能保证绝对安全,例如下面的代码:</p>
+
+<pre class="brush: js example-bad">var data = JSON.parse(responseText);
+addonElement.innerHTML = "&lt;div class='" + data.className + "'&gt;" +
+ "Your favorite color is now " + data.color +
+ "&lt;/div&gt;";</pre>
+
+<p>在其中,Here, the contents of <code>data.className</code> 或 <code>data.color</code> 的内容可能包含HTML代码使得标签提早关闭,并插入更多的HTML内容,之后关闭另一个标签。</p>
+
+<p>jQuery</p>
+
+<p>当使用jQuery的方法如 <code>attr()</code> 和 <code>text()</code> ,会清洗添加到DOM的内容。所以,上面“favorite color”例子采用jQuery实现会形如:</p>
+
+<pre class="brush: js example-good">var node = $("&lt;/div&gt;");
+node.addClass(data.className);
+node.text("Your favorite color is now " + data.color); </pre>
+
+<h2 id="处理HTML内容">处理HTML内容</h2>
+
+<p>当你知道处理外部源的内容是HTML的时候,添加到页面之前净化HTML是很关键的。净化HTML的最好办法是使用HTML净化的库或者一个带有HTML净化特性的模板引擎。在这一节,我们来看一些合适的工具以及使用方法。</p>
+
+<h3 id="HTML_净化">HTML 净化</h3>
+
+<p>An HTML sanitization library strips anything that could lead to script execution from HTML, so you can safely inject complete sets of HTML nodes from a remote source into your DOM. <a href="https://github.com/cure53/DOMPurify">DOMPurify</a>,是一个HTML净化的库,可以脱离任意会导致脚本执行的元素,以便安全注入远端源到HTML节点,这个库被很多不同的安全专家评估过,是很适合这种任务扩展的库。</p>
+
+<p><a href="https://github.com/cure53/DOMPurify">DOMPurify</a> 有一个简约版用于生产环境,purify.min.js. 你可以使用这个版本来适配你的扩展,例如你可以这样添加:</p>
+
+<pre class="brush: json">"content_scripts": [
+ {
+   "matches" : ["&lt;all_urls&gt;"],
+   "js": ["purify.min.js", "myinjectionscript.js"]
+ }
+]</pre>
+
+<p>之后,在myinjectionscript.js中你可以读取外部HTML并净化,之后添加到页面的DOM中:</p>
+
+<pre class="brush: js">var elem = document.createElement("div");
+var cleanHTML = DOMPurify.sanitize(externalHTML);
+elem.innerHTML = cleanHTML;</pre>
+
+<p>你可以使用任何方法添加净化后的HTML到DOM,例如jQuery’s <code>.html()</code> 方法。注意这种情况需要使用 Remember though that the <code>SAFE_FOR_JQUERY</code> 标记:</p>
+
+<pre class="brush: js">var elem = $("&lt;div/&gt;");
+var cleanHTML = DOMPurify.sanitize(externalHTML, { SAFE_FOR_JQUERY: true });
+elem.html(cleanHTML);</pre>
+
+<h3 id="模板引擎">模板引擎</h3>
+
+<p>另一个常见的模式是对一个页面创建本地HTML模板并通过远端的值来填空。这种方法被广泛应用,应该注意去避免构造函数的使用,可能会导致执行代码的注入。当模板引擎使用构造函数插入HTML到文档的时候会发生这种情况,如果用来注入原始HTML的变量是远端代码,这就属于上面介绍中的安全风险。</p>
+
+<p>例如,当使用<a href="https://mustache.github.io/">mustache templates</a> 你必须使用两个花括号<code>\{{variable}}</code>,来去掉任何HTML。使用三个花括号<code>\{\{{variable}}}</code> 必须避免注入原始HTML字符串到模板。</p>
+
+<p><a href="http://handlebarsjs.com/">Handlebars</a> 工作原理也是类似, <code>\{{variable}}</code> 。同时,如果创造了Handlebars helper使用 <code>Handlebars.SafeString</code> 使用<code>Handlebars.escapeExpression()</code> 来消除任何传给helper的动态参数。<code>Handlebars.SafeString</code> 的结果被认为是安全的,当插入到双handlebars的时候就不会做消除动作。</p>
+
+<p>在其他模板系统中也有类似的构造函数,需要有同样的考虑。</p>
+
+<h2 id="其他参考">其他参考</h2>
+
+<p>关于这个主题更多的信息,可以查看下面的文章</p>
+
+<ul>
+ <li>
+ <p><a href="https://owasp.org/www-community/xss-filter-evasion-cheatsheet">XSS (Cross Site Scripting) Prevention Cheat Sheet</a></p>
+ </li>
+</ul>
+
+<div id="gtx-trans" style="position: absolute; left: 220px; top: 3487px;">
+<div class="gtx-trans-icon"></div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_action/index.html b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_action/index.html
new file mode 100644
index 0000000000..1ec5a5aced
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_action/index.html
@@ -0,0 +1,50 @@
+---
+title: Toolbar button
+slug: Mozilla/Add-ons/WebExtensions/user_interface/Browser_action
+translation_of: Mozilla/Add-ons/WebExtensions/user_interface/Browser_action
+---
+<div>{{AddonSidebar}}</div>
+
+<p>常说的 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction">浏览器动作(browser action)</a>, 指通过在工具栏上上添加新按钮,提供用户互动选项,用户可点击按钮与你的扩展进行互动。<br>
+ <img alt="" src="https://mdn.mozillademos.org/files/15751/browser-action.png" style="display: block; height: 182px; margin-left: auto; margin-right: auto; width: 350px;"></p>
+
+<p>工具栏按钮(browser action)与地址栏按钮(page action)极为相似。区分其不同点及使用,请参看 <a href="/en-US/Add-ons/WebExtensions/user_interface/Page_actions#Page_actions_and_browser_actions">Page actions and browser actions</a>.</p>
+
+<h2 id="指定浏览器动作">指定浏览器动作</h2>
+
+<p>通过manifest.json里的关键字<code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code> 来定义浏览器动作的属性:</p>
+
+<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="key token">"browser_action":</span> <span class="punctuation token">{</span>
+ <span class="key token">"default_icon":</span> <span class="punctuation token">{</span>
+ <span class="key token">"19":</span> <span class="string token">"button/geo-19.png"</span><span class="punctuation token">,</span>
+ <span class="key token">"38":</span> <span class="string token">"button/geo-38.png"</span>
+ <span class="punctuation token">}</span><span class="punctuation token">,</span>
+ <span class="key token">"default_title":</span> <span class="string token">"Whereami?"</span>
+<span class="punctuation token">}</span></code></pre>
+
+<p>必须定义的键是 <code>default_icon</code>.</p>
+
+<p>有两种方法来指定浏览器动作:带弹出框(<a href="/en-US/Add-ons/WebExtensions/Popups">popup</a>)和不带弹出框(<a href="/en-US/Add-ons/WebExtensions/Popups">popup</a>)。</p>
+
+<p>如果不指定弹出框,当用户点击按钮时,点击事件将被发送至扩展,而扩展可用以下函数来捕获 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/BrowserAction/onClicked" title="Fired when a browser action icon is clicked. This event will not fire if the browser action has a popup."><code>browserAction.onClicked</code></a>:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js">browser<span class="punctuation token">.</span>browserAction<span class="punctuation token">.</span>onClicked<span class="punctuation token">.</span><span class="function token">addListener</span><span class="punctuation token">(</span>handleClick<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>如果指定了弹出框,当用户点击按钮时,点击事件将不会被发送,而是显示出弹出框。用户能够通过弹出框进行互动,并且点击框外区域时弹出框会自动关闭。请参看文章 <a href="/en-US/Add-ons/WebExtensions/Popups">Popup </a>来了解更多关于创建和管理弹出框的细节。</p>
+
+<p>注意一个扩展只能指定一个浏览器动作。</p>
+
+<p>可通过<code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction">browserAction</a></code> API在程序里更改你的浏览器动作的属性。</p>
+
+<h2 id="图标">图标</h2>
+
+<p>想了解更多关于如何创建浏览器动作图标信息,请参看<a class="grey-90 no-underline hover-no-underline" href="https://design.firefox.com/photon/index.html">Photon Design System</a> 文档里的 <a href="https://design.firefox.com/photon/visuals/iconography.html">Iconography</a> 部分.</p>
+
+<h2 id="范例">范例</h2>
+
+<p>在Github上的扩展范例库 <a href="https://github.com/mdn/webextensions-examples">webextensions-examples</a> 中有两个实现浏览器动作的例子:</p>
+
+<ul>
+ <li><a href="https://github.com/mdn/webextensions-examples/blob/master/bookmark-it/">bookmark-it</a> uses a browser action without a popup.</li>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/beastify">beastify</a> uses a browser action with a popup.</li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_styles/index.html b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_styles/index.html
new file mode 100644
index 0000000000..e0647bc543
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/browser_styles/index.html
@@ -0,0 +1,466 @@
+---
+title: Browser styles
+slug: Mozilla/Add-ons/WebExtensions/user_interface/Browser_styles
+tags:
+ - Browser style
+ - WebExtensions
+ - 扩展程序
+ - 指南
+ - 浏览器扩展程序
+ - 浏览器插件
+translation_of: Mozilla/Add-ons/WebExtensions/user_interface/Browser_styles
+---
+<div>{{AddonSidebar}}</div>
+
+<p>扩展程序包含的某些UI组件,例如: <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Popups">popups</a>, <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Sidebars">sidebars</a>, <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Options_pages">options pages</a> ,实际上可以用如下方式统一定义:</p>
+
+<ol>
+ <li>创建一个HTML文件用于描述该UI组件的页面结构</li>
+ <li>在manifest.json中添加字段 (<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code>, <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/page_action">page_action</a></code>, <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/sidebar_action">sidebar_action</a></code>, 或 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/options_ui">options_ui</a></code>) 以指向其对应的页面</li>
+</ol>
+
+<p>这种方式面临的一个挑战是如何使用浏览器自带的样式,以使得组件的UI表现与浏览器的UI风格相符。要解决这个问题,可以在该字段的配置中增加一个可字段 <code>browser_sytle</code> ,如果设置了这个字段并且值为 <code>true</code> ,  那么该UI组件的HTML将会被插入一个或多个样式表,样式表会使你的扩展程序的UI表现与浏览器的风格一致 (并且与其它同样应用了这个字段的扩展程序一致)。</p>
+
+<p>若使用了 <code>browser_style: true</code> , 你需要在不同的浏览器主题中测试你的扩展程序,以确保其UI表现和期望的一致。 </p>
+
+<div class="blockIndicator note">
+<p><strong>谷歌浏览器Google Chrome</strong> 和 欧朋浏览器 <strong>Opera</strong> 使用字段名 <code>chrome_style</code> 而非<code>browser_style</code>, 因此如果要适配它们,你需要同时添加这两个字段。</p>
+</div>
+
+<p>在火狐浏览器中,这个样式文件可以在 <code>chrome://browser/content/extension.css</code>查看。为Mac OS X系统额外准备的样式文件也可以在  <code>chrome://browser/content/extension-mac.css</code> 查看。</p>
+
+<p>大多数样式是自动应用的,但是某些元素需要添加非标准的类名 <code style="white-space: nowrap;">browser-style</code> 来获得其样式,如下表所示:</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Element</th>
+ <th scope="col">Example</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><code><a href="/en-US/docs/Web/HTML/Element/button">&lt;button&gt;</a></code></td>
+ <td>
+ <pre class="brush: html no-line-numbers">
+&lt;button class="browser-style"&gt;Click me&lt;/button&gt;</pre>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p><code><a href="/en-US/docs/Web/HTML/Element/select">&lt;select&gt;</a></code></p>
+ </td>
+ <td>
+ <pre class="brush: html no-line-numbers">
+&lt;select class="browser-style" name="select"&gt;
+ &lt;option value="value1"&gt;Value 1&lt;/option&gt;
+ &lt;option value="value2" selected&gt;Value 2&lt;/option&gt;
+ &lt;option value="value3"&gt;Value 3&lt;/option&gt;
+&lt;/select&gt;</pre>
+ </td>
+ </tr>
+ <tr>
+ <td><code><a href="/en-US/docs/Web/HTML/Element/textarea">&lt;textarea&gt;</a></code></td>
+ <td>
+ <pre class="brush: html no-line-numbers">
+&lt;textarea class="browser-style"&gt;Write here&lt;/textarea&gt;</pre>
+ </td>
+ </tr>
+ <tr>
+ <td>Parent of an <code><a href="/en-US/docs/Web/HTML/Element/input">&lt;input&gt;</a></code></td>
+ <td>
+ <pre class="brush: html no-line-numbers">
+&lt;div class="browser-style"&gt;
+ &lt;input type="radio" id="op1" name="choices" value="op1"/&gt;
+ &lt;label for="op1"&gt;Option 1&lt;/label&gt;
+
+ &lt;input type="radio" id="op2" name="choices" value="op2"/&gt;
+ &lt;label for="op2"&gt;Option 2&lt;/label&gt;
+&lt;/div&gt;</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<div class="blockIndicator note">
+<p>查看 {{bug(1465256)}} 以了解相关修订</p>
+</div>
+
+<h2 id="浏览器兼容性">浏览器兼容性</h2>
+
+<div class="hidden">兼容列表由结构化文件生成,如果你想要贡献此文件,请通过 <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 向我们发送pull request.</div>
+
+<p>{{Compat("webextensions.browser_style")}}</p>
+
+<h2 id="火狐面板组件Firefox_Panel_Components">火狐面板组件Firefox Panel Components</h2>
+
+<div class="blockIndicator nonStandard">
+<p><strong>非标准</strong><br>
+ 此功能不是通用标准,仅支持在firefox中使用</p>
+</div>
+
+<p><code>chrome://browser/content/extension.css</code> 样式文件中也包含了火狐面板组件的样式</p>
+
+<p><a href="https://firefoxux.github.io/StyleGuide/#/navigation">legacy Firefox Style Guide</a> 使用示例</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="col">Element</th>
+ <th scope="col">Example</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>Header</td>
+ <td>
+ <pre class="brush: html">
+&lt;header class="panel-section panel-section-header"&gt;
+ &lt;div class="icon-section-header"&gt;&lt;img src="image.svg"/&gt;&lt;/div&gt;
+ &lt;div class="text-section-header"&gt;Header&lt;/div&gt;
+&lt;/header&gt;</pre>
+ </td>
+ </tr>
+ <tr>
+ <td>Footer</td>
+ <td>
+ <pre class="brush: html">
+&lt;footer class="panel-section panel-section-footer"&gt;
+ &lt;button class="panel-section-footer-button"&gt;Cancel&lt;/button&gt;
+ &lt;div class="panel-section-footer-separator"&gt;&lt;/div&gt;
+ &lt;button class="panel-section-footer-button default"&gt;Confirm&lt;/button&gt;
+&lt;/footer&gt;</pre>
+ </td>
+ </tr>
+ <tr>
+ <td>Tabs</td>
+ <td>
+ <pre class="brush: html">
+&lt;div class="panel-section panel-section-tabs"&gt;
+ &lt;button class="panel-section-tabs-button selected"&gt;Tab&lt;/button&gt;
+ &lt;div class="panel-section-tabs-separator"&gt;&lt;/div&gt;
+ &lt;button class="panel-section-tabs-button"&gt;Tab&lt;/button&gt;
+ &lt;div class="panel-section-tabs-separator"&gt;&lt;/div&gt;
+ &lt;button class="panel-section-tabs-button"&gt;Tab&lt;/button&gt;
+&lt;/div&gt;</pre>
+ </td>
+ </tr>
+ <tr>
+ <td>Form</td>
+ <td>
+ <pre class="brush: html">
+&lt;div class="panel-section panel-section-formElements"&gt;
+ &lt;div class="panel-formElements-item"&gt;
+ &lt;label for="name01"&gt;Label:&lt;/label&gt;
+ &lt;input type="text" value="Name" id="name01" /&gt;
+ &lt;/div&gt;
+ &lt;div class="panel-formElements-item"&gt;
+ &lt;label for="picker01"&gt;Label:&lt;/label&gt;
+ &lt;select id="picker01"&gt;
+ &lt;option value="value1" selected="true"&gt;Dropdown&lt;/option&gt;
+ &lt;option value="value2"&gt;List Item&lt;/option&gt;
+ &lt;option value="value3"&gt;List Item&lt;/option&gt;
+ &lt;/select&gt;
+ &lt;/div&gt;
+ &lt;div class="panel-formElements-item"&gt;
+ &lt;label for="placeholder01"&gt;Label:&lt;/label&gt;
+ &lt;input type="text" placeholder="Placeholder" id="placeholder01" /&gt;
+ &lt;button name="expander" class="expander"&gt;&lt;/button&gt;
+ &lt;/div&gt;
+&lt;/div&gt;</pre>
+ </td>
+ </tr>
+ <tr>
+ <td>Menu</td>
+ <td>
+ <pre class="brush: html">
+&lt;div class="panel-section panel-section-list"&gt;
+ &lt;div class="panel-list-item"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;Ctrl-L&lt;/div&gt;
+ &lt;/div&gt;
+
+ &lt;div class="panel-list-item"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;&lt;/div&gt;
+ &lt;/div&gt;
+
+ &lt;div class="panel-section-separator"&gt;&lt;/div&gt;
+
+ &lt;div class="panel-list-item disabled"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;Disabled List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;&lt;/div&gt;
+ &lt;/div&gt;
+
+ &lt;div class="panel-section-separator"&gt;&lt;/div&gt;
+
+ &lt;div class="panel-list-item"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;&lt;/div&gt;
+ &lt;/div&gt;
+
+ &lt;div class="panel-list-item"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;&lt;/div&gt;
+ &lt;/div&gt;
+&lt;/div&gt;</pre>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h3 id="Example">Example</h3>
+
+<h4 id="HTML">HTML</h4>
+
+<pre class="brush: html">&lt;header class="panel-section panel-section-header"&gt;
+ &lt;div class="icon-section-header"&gt;&lt;!-- An image goes here. --&gt;&lt;/div&gt;
+ &lt;div class="text-section-header"&gt;Header&lt;/div&gt;
+&lt;/header&gt;
+
+&lt;div class="panel-section panel-section-list"&gt;
+ &lt;div class="panel-list-item"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;Ctrl-L&lt;/div&gt;
+ &lt;/div&gt;
+
+ &lt;div class="panel-list-item"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;&lt;/div&gt;
+ &lt;/div&gt;
+
+ &lt;div class="panel-section-separator"&gt;&lt;/div&gt;
+
+ &lt;div class="panel-list-item disabled"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;Disabled List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;&lt;/div&gt;
+ &lt;/div&gt;
+
+ &lt;div class="panel-section-separator"&gt;&lt;/div&gt;
+
+ &lt;div class="panel-list-item"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;&lt;/div&gt;
+ &lt;/div&gt;
+
+ &lt;div class="panel-list-item"&gt;
+ &lt;div class="icon"&gt;&lt;/div&gt;
+ &lt;div class="text"&gt;List Item&lt;/div&gt;
+ &lt;div class="text-shortcut"&gt;&lt;/div&gt;
+ &lt;/div&gt;
+&lt;/div&gt;
+
+&lt;footer class="panel-section panel-section-footer"&gt;
+ &lt;button class="panel-section-footer-button"&gt;Cancel&lt;/button&gt;
+ &lt;div class="panel-section-footer-separator"&gt;&lt;/div&gt;
+ &lt;button class="panel-section-footer-button default"&gt;Confirm&lt;/button&gt;
+&lt;/footer&gt;</pre>
+
+<div class="hidden">
+<h4 id="CSS">CSS</h4>
+
+<pre class="brush: css">/* Global */
+html,
+body {
+ background: white;
+ box-sizing: border-box;
+ color: #222426;
+ cursor: default;
+ display: flex;
+ flex-direction: column;
+ font: caption;
+ margin: 0;
+ padding: 0;
+ -moz-user-select: none;
+}
+
+body * {
+ box-sizing: border-box;
+ text-align: start;
+}
+
+button.panel-section-footer-button,
+button.panel-section-tabs-button {
+ color: inherit;
+ background-color: unset;
+ font: inherit;
+ text-shadow: inherit;
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+ border: none;
+}
+
+/* Panel Section */
+.panel-section {
+ display: flex;
+ flex-direction: row;
+}
+
+.panel-section-separator {
+ background-color: rgba(0, 0, 0, 0.15);
+ min-height: 1px;
+}
+
+/* Panel Section - Header */
+.panel-section-header {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.15);
+ padding: 16px;
+}
+
+.panel-section-header &gt; .icon-section-header {
+ background-position: center center;
+ background-repeat: no-repeat;
+ height: 32px;
+ margin-right: 16px;
+ position: relative;
+ width: 32px;
+}
+
+.panel-section-header &gt; .text-section-header {
+ align-self: center;
+ font-size: 1.385em;
+ font-weight: lighter;
+}
+
+/* Panel Section - List */
+.panel-section-list {
+ flex-direction: column;
+ padding: 4px 0;
+}
+
+.panel-list-item {
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ height: 24px;
+ padding: 0 16px;
+}
+
+.panel-list-item:not(.disabled):hover {
+ background-color: rgba(0, 0, 0, 0.06);
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+.panel-list-item:not(.disabled):hover:active {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+
+.panel-list-item.disabled {
+ color: #999;
+}
+
+.panel-list-item &gt; .icon {
+ flex-grow: 0;
+ flex-shrink: 0;
+}
+
+.panel-list-item &gt; .text {
+ flex-grow: 10;
+}
+
+.panel-list-item &gt; .text-shortcut {
+ color: #808080;
+ font-family: "Lucida Grande", caption;
+ font-size: .847em;
+ justify-content: flex-end;
+}
+
+.panel-section-list .panel-section-separator {
+ margin: 4px 0;
+}
+
+/* Panel Section - Footer */
+.panel-section-footer {
+ background-color: rgba(0, 0, 0, 0.06);
+ border-top: 1px solid rgba(0, 0, 0, 0.15);
+ color: #1a1a1a;
+ display: flex;
+ flex-direction: row;
+ height: 41px;
+ margin-top: -1px;
+ padding: 0;
+}
+
+.panel-section-footer-button {
+ flex: 1 1 auto;
+ height: 100%;
+ margin: 0 -1px;
+ padding: 12px;
+ text-align: center;
+}
+
+.panel-section-footer-button &gt; .text-shortcut {
+ color: #808080;
+ font-family: "Lucida Grande", caption;
+ font-size: .847em;
+}
+
+.panel-section-footer-button:hover {
+ background-color: rgba(0, 0, 0, 0.06);
+}
+
+.panel-section-footer-button:hover:active {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+
+.panel-section-footer-button.default {
+ background-color: #0996f8;
+ box-shadow: 0 1px 0 #0670cc inset;
+ color: #fff;
+}
+
+.panel-section-footer-button.default:hover {
+ background-color: #0670cc;
+ box-shadow: 0 1px 0 #005bab inset;
+}
+
+.panel-section-footer-button.default:hover:active {
+ background-color: #005bab;
+ box-shadow: 0 1px 0 #004480 inset;
+}
+
+.panel-section-footer-separator {
+ background-color: rgba(0, 0, 0, 0.1);
+ width: 1px;
+ z-index: 99;
+}</pre>
+
+<hr>
+<pre class="brush: css">/* Example specific – not part of chrome://browser/content/extension.css */
+body {
+ background: #fcfcfc;
+ background-clip: padding-box;
+ border: 1px solid rgba(24,26,27,.2);
+ box-shadow: 0 3px 5px rgba(24,26,27,.1),0 0 7px rgba(24,26,27,.1);
+ box-sizing: content-box;
+ margin: 2em auto .5em;
+ width: 384px;
+}
+
+html {
+ min-height: 100vh;
+}
+
+html &gt; body {
+ margin: auto;
+}
+
+.icon-section-header {
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj48Y2lyY2xlIGZpbGw9IiMzNjM5NTkiIGN4PSIxNSIgY3k9IjE1IiByPSIxNSIvPjwvc3ZnPg==");
+}</pre>
+</div>
+
+<h4 id="Result若查看失败,请切回英文版查看">Result(若查看失败,请切回英文版查看)</h4>
+
+<p>{{EmbedLiveSample("Example","640","360")}}</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/user_interface/context_menu_items/index.html b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/context_menu_items/index.html
new file mode 100644
index 0000000000..2844e7319a
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/context_menu_items/index.html
@@ -0,0 +1,48 @@
+---
+title: Context menu items
+slug: Mozilla/Add-ons/WebExtensions/user_interface/Context_menu_items
+translation_of: Mozilla/Add-ons/WebExtensions/user_interface/Context_menu_items
+---
+<div>{{AddonSidebar}}</div>
+
+<div>
+<p>This user interface option adds one or more items to a browser context menu. This is the context menu available when a user right-clicks on a web page. Tabs can have context menus also, available through the <a href="/en-US/Add-ons/WebExtensions/API/menus">browser.menus API</a>.</p>
+
+<p><img alt="Example of content menu items added by a WebExtension, from the context-menu-demo example" src="https://mdn.mozillademos.org/files/15051/context_menu_example.png" style="display: block; height: 587px; margin-left: auto; margin-right: auto; width: 573px;"></p>
+
+<p>You would use this option to expose features that are relevant to specific browser or web page contexts. For example, you could show features to open a graphic editor when the user clicks on an image or offer a feature to save page content when part of a page is selected. You can add plain menu items, checkbox items, radio button groups, and separators to menus. Once a context menu item has been added using {{WebExtAPIRef("contextMenus.create")}} it's displayed in all browser tabs, but you can hide it by removing it with {{WebExtAPIRef("contextMenus.remove")}}.</p>
+
+<h2 id="Specifying_context_menu_items">Specifying context menu items</h2>
+
+<p>You manage context menu items programmatically, using the {{WebExtAPIRef("contextMenus")}} API. However, you need to request the <code>contextMenus</code> permission in your manifest.json to be able to take advantage of the API.</p>
+
+<pre class="brush: json">"permissions": ["contextMenus"]</pre>
+
+<p>You can then add (and update or delete) the context menu items in your extension's background script. To create a menu item you specify an id, its title, and the context menus it should appear on:</p>
+
+<pre class="brush: js">browser.contextMenus.create({
+ id: "log-selection",
+ title: browser.i18n.getMessage("contextMenuItemSelectionLogger"),
+ contexts: ["selection"]
+}, onCreated);</pre>
+
+<p>Your extension then listens for clicks on the menu items. The passed information about the item clicked, the context where the click happened, and details of the tab where the click took place can then be used to invoke the appropriate extension functionality.</p>
+
+<pre class="brush: js">browser.contextMenus.onClicked.addListener(function(info, tab) {
+ switch (info.menuItemId) {
+ case "log-selection":
+ console.log(info.selectionText);
+ break;
+ ...
+ }
+})</pre>
+
+<h2 id="Examples">Examples</h2>
+
+<p>The <a class="external external-icon" href="https://github.com/mdn/webextensions-examples">webextensions-examples</a> repo on GitHub, contains several examples of extensions that use context menu items:</p>
+
+<ul>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/menu-demo">menu-demo</a> adds several items to the browser's context menu.</li>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/context-menu-copy-link-with-types">context-menu-copy-link-with-types</a> adds a context menu item to links that copies the URL to the clipboard, as plain text and rich HTML.</li>
+</ul>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/user_interface/devtools_panels/index.html b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/devtools_panels/index.html
new file mode 100644
index 0000000000..8f55647526
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/devtools_panels/index.html
@@ -0,0 +1,61 @@
+---
+title: devtools panels
+slug: Mozilla/Add-ons/WebExtensions/user_interface/devtools_panels
+translation_of: Mozilla/Add-ons/WebExtensions/user_interface/devtools_panels
+---
+<div>{{AddonSidebar}}</div>
+
+<div class="note">
+<p>This feature is available since Firefox 54.</p>
+</div>
+
+<p>When an extension provides tools that are of use to developers, it's possible to add a UI for them to the browser's developer tools as a new panel.</p>
+
+<p><img alt='Simple example showing the addition of "My panel" to the Developer Tools tabs.' src="https://mdn.mozillademos.org/files/15746/developer_panel_tab.png" style="display: block; height: 112px; margin-left: auto; margin-right: auto; width: 350px;"></p>
+
+<h2 id="Specifying_a_developer_tools_panel">Specifying a developer tools panel</h2>
+
+<p>A developer tools panel is added using the <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.panels">devtools.panels</a></code> API, which in turn needs to be run from a special devtools page.</p>
+
+<p>Add the devtools page by including the <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/devtools_page">devtools_page</a></code> key in extension's <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a> and provide the location of the page's HTML file in the extension:</p>
+
+<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="key token">"devtools_page":</span> <span class="string token">"devtools-page.html"</span></code></pre>
+
+<p>From the devtools page, call a script that will add the devtools panel:</p>
+
+<pre class="brush: html">&lt;body&gt;
+  &lt;script src="devtools.js"&gt;&lt;/script&gt;
+&lt;/body&gt;</pre>
+
+<p>In the script, create the devtools panel by specifying the panel's title, icon, and HTML file that provides the panel's content:</p>
+
+<pre class="brush: js">function handleShown() {
+ console.log("panel is being shown");
+}
+
+function handleHidden() {
+ console.log("panel is being hidden");
+}
+
+browser.devtools.panels.create(
+ "My Panel", // title
+ "icons/star.png", // icon
+ "devtools/panel/panel.html" // content
+).then((newPanel) =&gt; {
+ newPanel.onShown.addListener(handleShown);
+ newPanel.onHidden.addListener(handleHidden);
+});</pre>
+
+<p>The extension can now run code in the inspected window using <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/devtools.inspectedWindow/eval"><code>devtools</code>.inspectedWindow.eval()</a></code> or by injecting a content script via the background script by passing a message. You can find more details on how to do this in <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Extending_the_developer_tools">Extending the developer tools.</a></p>
+
+<h2 id="Developer_panel_design">Developer panel design</h2>
+
+<p>For details on how to design your developer panel's web page to match the style of Firefox, see the <a class="grey-90 no-underline hover-no-underline" href="https://design.firefox.com/photon/index.html">Photon Design System</a> documentation.</p>
+
+<h2 id="Icons">Icons</h2>
+
+<p>For details on how to create icons to use with your developer tools panel, see <a href="https://design.firefox.com/photon/visuals/iconography.html">Iconography</a> in the <a class="grey-90 no-underline hover-no-underline" href="https://design.firefox.com/photon/index.html">Photon Design System</a> documentation.</p>
+
+<h2 id="Examples">Examples</h2>
+
+<p>The <a href="https://github.com/mdn/webextensions-examples">webextensions-examples</a> repository on GitHub includes the <a href="https://github.com/mdn/webextensions-examples/blob/master/devtools-panels/">devtools-panels</a> example which implements a devtools panel.</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/user_interface/index.html b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/index.html
new file mode 100644
index 0000000000..f34e594284
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/index.html
@@ -0,0 +1,92 @@
+---
+title: User interface
+slug: Mozilla/Add-ons/WebExtensions/user_interface
+translation_of: Mozilla/Add-ons/WebExtensions/user_interface
+---
+<div>{{AddonSidebar}}</div>
+
+<p>为了能给用户提供在不同场景下都具有价值的功能, WebExtensions 提供了许多的用户界面选项。下面是这些选项的摘要,在本章中将会对每个选项做出更详细的说明。</p>
+
+<div class="note">
+<p>想要使你的扩展能提供良好的用户体验吗? 请查看文章<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/User_experience_best_practices">用户体验的最佳实践</a> .</p>
+</div>
+
+<table class="standard-table">
+ <thead>
+ <tr>
+ <th scope="col">UI 选项</th>
+ <th scope="col">描述</th>
+ <th scope="col" style="width: 350px;">实例</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Browser_action">浏览器工具栏按钮</a>(浏览器行为)</td>
+ <td>工具栏上一个可点击的按钮,点击时将事件派发到附件组件上。默认情况下,这个按钮在栏位中是可见的。</td>
+ <td><img alt="Example of a WebExtension toolbar button" src="https://mdn.mozillademos.org/files/12966/browser-action.png" style="height: 99px; width: 350px;"></td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Page_actions">带有弹出面板的工具栏按钮</a></td>
+ <td>当这个在工具栏上的按钮被点击时,它会弹出一个面板。这个面板使用 HTML 文档编写,用于处理与用户的交互行为。</td>
+ <td><img alt="Example of a WebExtension toolbar button with a popup" src="https://mdn.mozillademos.org/files/14039/popup-shadow.png" style="height: 156px; width: 350px;"></td>
+ </tr>
+ <tr>
+ <td><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Page_actions">地址栏菜单按钮</a>(页面行为)</td>
+ <td>这个按钮位于浏览器地址栏菜单条,按钮被点击的时候可以派发一个事件出来。默认情况下,这个按钮在所有tab上都是隐藏的.</td>
+ <td><img alt="Example showing an address bar button (page action)" src="https://mdn.mozillademos.org/files/15047/address_bar_button.png" style="height: 127px; width: 350px;"></td>
+ </tr>
+ <tr>
+ <td>带有<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Popups">弹出面板</a>的地址栏菜单按钮</td>
+ <td>地址栏菜单按钮被点击时,会弹出一个面板,这个面板通过HTML文档定义,用于处理用户交互。</td>
+ <td><img alt="Example of a popup on the address bar button" src="https://mdn.mozillademos.org/files/15053/page_action_popup.png" style="height: 250px; width: 330px;"></td>
+ </tr>
+ <tr>
+ <td><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/user_interface/Context_menu_items">上下文菜单项</a></td>
+ <td>在一个或多个网页上下文菜单中的菜单项,复选框和单选按钮.菜单项也可以通过添加分隔栏进行分组,当一个菜单项被点击时,一个事件将会被派发至附加组件.</td>
+ <td><img alt="" src="https://mdn.mozillademos.org/files/15051/context_menu_example.png" style="height: 359px; width: 350px;"></td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Sidebars">侧边栏</a></td>
+ <td>
+ <p dir="ltr">一个在网页边显示的HTML文档,每页都有其特定的内容. 每当扩展安装时侧边栏将会打开,但最终还是遵循用户的侧边栏可见性设置. 侧边栏内的用户交互通过HTML文档处理.</p>
+ </td>
+ <td><img alt="Example of a WebExtension's sidebar" src="https://mdn.mozillademos.org/files/14825/bookmarks-sidebar.png" style="height: 209px; width: 350px;"></td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Options_pages">选项页面</a></td>
+ <td>一个可以使你定义可以更改的扩展首选项的页面. 用户可以从浏览器的附加组件管理器中访问此页面.</td>
+ <td><img alt="Example showing the options page content added in the favorite colors example." src="https://mdn.mozillademos.org/files/15055/options_page.png" style="height: 259px; width: 350px;"></td>
+ </tr>
+ <tr>
+ <td><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Bundled_web_pages">扩展页面</a></td>
+ <td>
+ <p>在单独的窗口或页面中使用扩展提供的页面来提供表单,帮助或其他任何需要的内容.</p>
+ </td>
+ <td><img alt="Example of a simple bundled page displayed as a detached panel." src="https://mdn.mozillademos.org/files/15063/bundled_page_as_panel_small.png" style="height: 180px; width: 350px;"></td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Notifications">通知</a></td>
+ <td>通过底层操作系统的通知机制向用户显示的短暂通知. 当用户点击或者通知关闭时(用户关闭或超时关闭)派发事件到扩展程序.</td>
+ <td><img alt="Example notification from a WebExtension" src="https://mdn.mozillademos.org/files/14043/notify-shadowed.png" style="height: 95px; width: 350px;"></td>
+ </tr>
+ <tr>
+ <td><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Omnibox">地址栏建议</a></td>
+ <td>当用户输入关键词时提供自定义的地址栏建议.</td>
+ <td><img alt="Example showing the result of the firefox_code_search WebExtension's customization of the address bar suggestions." src="https://mdn.mozillademos.org/files/15059/omnibox_example_small.png" style="height: 242px; width: 350px;"></td>
+ </tr>
+ <tr>
+ <td><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/devtools_panels">开发者工具面板</a></td>
+ <td>在浏览器的开发者工具中显示的一个关联了HTML文档的标签.</td>
+ <td><img alt="New panel tab in the Developer Tools tab bar" src="https://mdn.mozillademos.org/files/15049/developer_panel_tab.png" style="height: 180px; width: 350px;"></td>
+ </tr>
+ </tbody>
+</table>
+
+<p>以下的操作指南提供了一些创建用户界面选项的指导;</p>
+
+<ul>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Add_a_button_to_the_toolbar">在工具栏中添加一个按钮</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Implement_a_settings_page">实现一个设置页面</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Extending_the_developer_tools">扩展开发人员工具</a></li>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Browser_styles">浏览器样式</a></li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/user_interface/page_actions/index.html b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/page_actions/index.html
new file mode 100644
index 0000000000..fe3901c4a8
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/page_actions/index.html
@@ -0,0 +1,93 @@
+---
+title: 地址栏按钮
+slug: Mozilla/Add-ons/WebExtensions/user_interface/Page_actions
+translation_of: Mozilla/Add-ons/WebExtensions/user_interface/Page_actions
+---
+<div>{{AddonSideBar}}</div>
+
+<div>通常来说的page action,是添加到浏览器地址栏中的按钮。用户通过点击这个按钮与你的扩展进行交互。</div>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15745/address_bar_button.png" style="display: block; height: 174px; margin-left: auto; margin-right: auto; width: 350px;"></p>
+
+<h2 id="地址栏按钮(Page_actions)和工具栏按钮(_browser_actions)">地址栏按钮(Page actions)和工具栏按钮( browser actions)</h2>
+
+<p>地址栏按钮(或 page action) 与工具栏按钮(或 browser action)非常相似。</p>
+
+<p>其不同之处为:</p>
+
+<ul>
+ <li>位置:
+ <ul>
+ <li>地址栏按钮是显示在浏览器的地址栏内;</li>
+ <li>工具栏按钮不是显示在地址栏内,而是在浏览器的工具栏上。</li>
+ </ul>
+ </li>
+ <li>可见性:
+ <ul>
+ <li>地址栏按钮默认是隐藏的(尽管可以通过manifest中“show_matches和hide_matches来改变),而你可以在特定tabs中调用pageAction.show()和pageAction.hide()来显示或隐藏它。</li>
+ <li>工具栏按钮总是可见的。</li>
+ </ul>
+ </li>
+</ul>
+
+<p>当动作(行为)与当前页面关联时,使用地址栏按钮,而当动作(行为)与浏览器相关或与多个页面相关时使用工具栏按钮。例如:</p>
+
+<table class="fullwidth-table standard-table">
+ <thead>
+ <tr>
+ <th scope="row">类型</th>
+ <th scope="col">书签动作</th>
+ <th scope="col">内容动作</th>
+ <th scope="col">标签操作</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <th scope="row">page action</th>
+ <td>将本页面保存到书签</td>
+ <td>Reddit enhancement</td>
+ <td>Send tab</td>
+ </tr>
+ <tr>
+ <th scope="row">browser action</th>
+ <td>显示所有书签</td>
+ <td>使能ad-blocking</td>
+ <td>同步所有打开的标签</td>
+ </tr>
+ </tbody>
+</table>
+
+<p> </p>
+
+<h2 id="定义地址栏按钮">定义地址栏按钮</h2>
+
+<p>你可以在manifest.json中使用page_action键定义地址栏按钮的属性:</p>
+
+<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="key token">"page_action":</span> <span class="punctuation token">{</span>
+ <span class="key token">"browser_style":</span> <span class="keyword token">true</span><span class="punctuation token">,</span>
+ <span class="key token">"default_icon":</span> <span class="punctuation token">{</span>
+ <span class="key token">"19":</span> <span class="string token">"button/geo-19.png"</span><span class="punctuation token">,</span>
+ <span class="key token">"38":</span> <span class="string token">"button/geo-38.png"</span>
+ <span class="punctuation token">}</span><span class="punctuation token">,</span>
+ <span class="key token">"default_title":</span> <span class="string token">"Whereami?"</span>
+<span class="punctuation token">}</span></code></pre>
+
+<p>仅default_icon是强制(必需)的。</p>
+
+<p>有两种方式定义地址栏按钮:带popup窗口和无popup窗口。如果你没有指定一个popup,则当用户点击此按钮时,事件被派送到使用<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/pageAction/onClicked">pageAction.onClicked</a>侦听器的扩展:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js">browser<span class="punctuation token">.</span>pageAction<span class="punctuation token">.</span>onClicked<span class="punctuation token">.</span><span class="function token">addListener</span><span class="punctuation token">(</span>handleClick<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>如果你指定了一个popup,则点击事件不被派送,在用户点击按钮时显示popup。用户可以与popup进行交互,并且当用户点击popup以外区域时,popup自动关闭。参见<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Popups">Popup</a>可获得创建和管理popups更详细内容。</p>
+
+<p>注意你的扩展只能有一个地址栏按钮。</p>
+
+<p>通过使用<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/pageAction">pageAction</a> API,你可以以编程方式修改地址栏按钮的任何属性。</p>
+
+<h2 id="Icons">Icons</h2>
+
+<p>如何创建用于地址栏按钮的ICONS的详细内容,请参见<a href="https://design.firefox.com/photon/index.html">Photon Design System</a>文档中的<a href="https://design.firefox.com/photon/visuals/iconography.html">Iconography</a>节。</p>
+
+<h2 id="示例">示例</h2>
+
+<p>GitHub上的 <a href="https://github.com/mdn/webextensions-examples">webextensions-examples</a> 库中包括了实现无popup地址栏按钮的例子 <a href="https://github.com/mdn/webextensions-examples/tree/master/chill-out">chill-out</a> 。</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/user_interface/侧边栏/index.html b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/侧边栏/index.html
new file mode 100644
index 0000000000..8d13bfaf2c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/user_interface/侧边栏/index.html
@@ -0,0 +1,53 @@
+---
+title: 侧边栏
+slug: Mozilla/Add-ons/WebExtensions/user_interface/侧边栏
+translation_of: Mozilla/Add-ons/WebExtensions/user_interface/Sidebars
+---
+<div>{{AddonSidebar}}</div>
+
+<div>
+<p>A sidebar is a pane that is displayed at the side of the browser window, next to the web page. The browser provides a UI that enables the user to see the currently available sidebars and to select a sidebar to display. For example, Firefox has a "View &gt; Sidebar" menu. Only one sidebar can be shown at a time, and that sidebar will be displayed for all tabs and all browser windows.</p>
+
+<p>The browser may include a number of built-in sidebars. For example, Firefox includes a sidebar for interacting with bookmarks:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15755/bookmarks-sidebar.png" style="display: block; height: 423px; margin-left: auto; margin-right: auto; width: 350px;">Using the <code>sidebar_action</code> manifest.json key, an extension can add its own sidebar to the browser. It will be listed alongside the built-in sidebars, and the user will be able to open it using the same mechanism as for the built-in sidebars.</p>
+
+<p>就像浏览器的弹出页面,侧边栏也是一个HTML文档。当用户打开侧边栏时,HTML文档载入打开的浏览器窗口。每个窗口有一个该文档的实例。打开一个新窗口时,该窗口获得自己的文档实例</p>
+
+<p>可以使用函数{{WebExtAPIRef("sidebarAction.setPanel()")}}指定侧边栏仅用于指定的某个标签,使用{{WebExtAPIRef("windows.getCurrent()")}} 侧边栏知道自己属于哪一个标签。</p>
+
+<pre class="brush: js">// sidebar.js
+browser.windows.getCurrent({populate: true}).then((windowInfo) =&gt; {
+ myWindowId = windowInfo.id;
+});</pre>
+
+<p>不同的窗口使用不同的侧边栏是非常有用的,这是一个实例 ,见<a href="https://github.com/mdn/webextensions-examples/tree/master/annotate-page">"annotate-page" example</a>.</p>
+
+<p>侧边栏俱有和后台程序以及弹出窗口相同的API权限,在非隐藏模式下,侧边栏使用API {{WebExtAPIRef("runtime.getBackgroundPage()")}} 可以直接访问后台页面,使用 API 如{{WebExtAPIRef("tabs.sendMessage()")}} 与content scripts交互,使用API 如 {{WebExtAPIRef("runtime.sendNativeMessage()")}} 与原生应用交互。</p>
+
+<p>关闭窗口或关闭侧边栏时,侧边栏文档退出。这意味着和后台页面不同,侧边栏文档不是一直住留,也不像弹出窗口,只要用户与页面交互 ,它就一直存在。</p>
+
+<p>使用侧边栏的扩展载入时,侧边栏自动打开。这是为了帮助用户知道扩展俱有侧边栏。注意不能通过编程的方式打开侧边栏:侧边栏只能由用户打开。</p>
+
+<h2 id="声明侧边栏">声明侧边栏</h2>
+
+<p>声明侧边栏,只需在manifest.json中指 定关键字  <code><a href="/en-US/Add-ons/WebExtensions/manifest.json/sidebar_action">sidebar_action</a></code>    并同时指定title 和 icon:</p>
+
+<pre class="brush: json">"sidebar_action": {
+ "default_title": "My sidebar",
+ "default_panel": "sidebar.html",
+ "default_icon": "sidebar_icon.png"
+}</pre>
+
+<p>使用API {{WebExtAPIRef("sidebarAction")}} ,你可以用编程的方式修改title panel icon。</p>
+
+<p>浏览器提供的显示侧边栏的UI中,title和icon显示给用户,如Firefox菜单栏的"View &gt; Sidebar"</p>
+
+<h2 id="Sidebar_design">Sidebar design</h2>
+
+<p>For details on how to design your sidebar's web page to match the style of Firefox, see the <a class="grey-90 no-underline hover-no-underline" href="https://design.firefox.com/photon/index.html">Photon Design System</a> documentation.</p>
+
+<h2 id="Example">Example</h2>
+
+<p>The <a href="https://github.com/mdn/webextensions-examples">webextensions-examples</a> repository on GitHub includes the <a href="https://github.com/mdn/webextensions-examples/tree/master/annotate-page">annotate-page</a> example which implements a sidebar.</p>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/walkthrough/index.html b/files/zh-cn/mozilla/add-ons/webextensions/walkthrough/index.html
new file mode 100644
index 0000000000..962e04d404
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/walkthrough/index.html
@@ -0,0 +1,488 @@
+---
+title: 你的第二个 WebExtension
+slug: Mozilla/Add-ons/WebExtensions/Walkthrough
+translation_of: Mozilla/Add-ons/WebExtensions/Your_second_WebExtension
+---
+<p>{{AddonSidebar}}</p>
+
+<p>如果你已经阅读了 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension">你的第一个扩展</a>,那么你现在已经知道如何写一个扩展了。在这篇文章,我们将写一个稍微复杂一点点的扩展来为你展示更多的一些API 。</p>
+
+<p>这个扩展会添加一个新按钮到 Firefox 的工具栏。在用户点击该按钮时,我们会显示一个弹出窗(popup)来让他们选择一种动物。在他们选择之后,我们会将当前网页替换为他所选动物的图片。</p>
+
+<p>要实现这点,我们将:</p>
+
+<ul>
+ <li><strong>定义一个浏览器动作(browser action),这用来附加一个按钮到 Firefox 的工具栏。</strong><br>
+ 对于该按钮,我们将提供:
+ <ul>
+ <li>一个文件名为 "beasts-32.png" 的图标</li>
+ <li>按钮被按下时要打开的弹出窗。该弹出窗将包含 HTML、CSS 和 JavaScript。</li>
+ </ul>
+ </li>
+ <li><strong>为扩展定义一个图标</strong>,叫做“beasts-48.png”。这个将会在Add-ons管理器中显示。</li>
+ <li><strong>写一个内容脚本 "beastify.js",用于注入到网页中。</strong><br>
+ 这是用来实际修改页面的代码。</li>
+ <li><strong>打包一些动物的图像,用以替换网页中的图像。</strong><br>
+ 我们让图像成为 “Web 可访问资源”( web accessible resources ),以便页面可以引用它们。</li>
+</ul>
+
+<p>你可以想象这样的扩展的整体结构:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/13671/Untitled-1.png"></p>
+
+<p>这是一个非常简单的扩展,但也展示了 WebExtensions API 的许多基本概念:</p>
+
+<ul>
+ <li>添加一个按钮到工具栏</li>
+ <li>定义一个将使用 HTML、CSS 和 JavaScript 的弹出窗</li>
+ <li>注入content scripts到网页</li>
+ <li>content scripts与扩展的其他部分之间的通信</li>
+ <li>打包你的扩展的资源,使其可被网页所用</li>
+</ul>
+
+<p>你可以在 GitHub 找到<a href="https://github.com/mdn/webextensions-examples/tree/master/beastify">该扩展的完整的源代码</a>。</p>
+
+<p>写这个扩展,你需要45或更高版本的firefox。</p>
+
+<h2 id="编写扩展">编写扩展</h2>
+
+<p>创建一个新目录,并切换到该目录:</p>
+
+<ol>
+ <li>
+ <pre class="brush: bash">mkdir beastify
+cd beastify</pre>
+ </li>
+</ol>
+
+<h3 id="manifest.json">manifest.json</h3>
+
+<p>现在创建一个名为 "manifest.json" 的文件,并对其添加下列内容:</p>
+
+<ol>
+ <li>
+ <pre><code>{
+
+ "manifest_version": 2,
+ "name": "Beastify",
+ "version": "1.0",
+
+ "description": "Adds a browser action icon to the toolbar. Click the button to choose a beast. The active tab's body content is then replaced with a picture of the chosen beast. See https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Examples#beastify",
+ "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/beastify",
+ "icons": {
+ "48": "icons/beasts-48.png"
+ },
+
+ "permissions": [
+ "activeTab"
+ ],
+
+ "browser_action": {
+ "default_icon": "icons/beasts-32.png",
+ "default_title": "Beastify",
+ "default_popup": "popup/choose_beast.html"
+ },
+
+ "web_accessible_resources": [
+ "beasts/frog.jpg",
+ "beasts/turtle.jpg",
+ "beasts/snake.jpg"
+ ]
+
+}</code></pre>
+ </li>
+</ol>
+
+<ul>
+ <li>最开始的三个属性: <strong><code>manifest_version</code></strong>, <strong><code>name</code></strong>, <strong><code>version</code></strong>, 是必须的并且包含了插件最基本的信息。</li>
+ <li><a href="/zh-CN/docs/Mozilla/Tech/XUL/Attribute/description">description </a>和 <a href="/Add-ons/WebExtensions/manifest.json/homepage_url">homepage_url </a>是可选的,但是推荐填写,因为它们提供关于扩展的有用信息。</li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/manifest.json/icons">icons </a>也是可选但推荐的,它决定了插件在附加组件中的图标。</li>
+ <li><strong><code>permissions</code></strong> 列出了插件所需要的权限。在这里我们仅需要 <a href="/zh-CN/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission">activeTab permission</a>。</li>
+ <li><strong><code>browser_action</code></strong> 指定了工具栏按钮。我们在这里提供了三个信息片段:
+ <ul>
+ <li><strong><code>default_icon</code></strong> 是必须的,指定了按钮的图标。</li>
+ <li><strong><code>default_title</code></strong> 是可选的,用于按钮的提示。</li>
+ <li><strong><code>default_popup</code></strong>  在你想要当用户点击按钮时显示出一个弹出窗时使用。而在这里,我们需要,所以我们列入这个键并将其指向扩展中包括的一个HTML文件。</li>
+ </ul>
+ </li>
+ <li><strong><code>web_accessible_resources</code></strong> 列出了页面可访问的资源。例如由于当前插件使用动物图像替换了页面原有的图像,当前的动物图像要可以被页面访问。</li>
+</ul>
+
+<p>需要注意,所有路径是相对于 manifest.json 。</p>
+
+<h3 id="图标">图标</h3>
+
+<p>插件应该有一个图标。这个图标被用于显示在附加组件管理器中(可以通过"about:addons"来访问)。当前插件中manifest.json指定了我们插件的图标位于"icons/beasts-48.png"。</p>
+
+<p>创建“icons”文件夹,并将图标命名为“beasts-48.png”。你可以使用我们例子中的<a href="https://github.com/mdn/webextensions-examples/blob/master/beastify/icons/beasts-48.png">图标</a>,它是从 <a href="https://www.iconfinder.com/iconsets/free-retina-icon-set">Aha-Soft’s Free Retina iconset</a> 截取的,使用需要遵循该网站的<a href="http://www.aha-soft.com/free-icons/free-retina-icon-set//zh-CN/docs/">许可证</a>。</p>
+
+<p>如果你使用自己的图标,它的尺寸应该是48<math><semantics><mo>×</mo><annotation encoding="TeX">\times</annotation></semantics></math>48像素的。同时,对于高分辨率的设备,可以提供96<math><semantics><mo>×</mo><annotation encoding="TeX">\times</annotation></semantics></math>96像素的图片。此时,manifest.json应当这样配置:</p>
+
+<ol>
+ <li>
+ <pre class="brush: json line-numbers language-json"><code class="language-json"><span class="key token">"icons":</span> <span class="punctuation token">{</span>
+ <span class="key token">"48":</span> <span class="string token">"icons/beasts-48.png"</span><span class="punctuation token">,</span>
+ <span class="key token">"96":</span> <span class="string token">"icons/beasts-96.png"</span>
+<span class="punctuation token">}</span></code></pre>
+ </li>
+</ol>
+
+
+
+<h3 id="工具栏按钮">工具栏按钮</h3>
+
+<p>工具栏按钮也需要一个图标,并且我们的 manifest.json 承诺我们会为该工具栏在 "icons/beasts-32.png" 提供一个图标。</p>
+
+<p>将一个图标命名为为 "beasts-32.png"并保存到"icons"文件夹。你可以使用例子中的<a href="https://github.com/mdn/webextensions-examples/blob/master/beastify/icons/beasts-32.png">图片</a>,它是取自 <a href="http://www.iconbeast.com/free">IconBeast Lite 图标集</a>并按其<a href="http://www.iconbeast.com/faq/">许可协议</a>授权使用。</p>
+
+<p>如果你没有弹出窗,用户点击的事件会直接分派到你的插件中。<span style="line-height: 1.5;">如果你制作了弹出窗,用户点击会直接打开这个弹出窗,而不会被分派给插件。</span><span style="line-height: 1.5;">本例中我们需要弹出窗,因此我们现在开始写它。</span></p>
+
+<h3 id="弹出窗">弹出窗</h3>
+
+<p>该弹出窗的函数是让用户选择三种动物的其中一种。</p>
+
+<p>在根目录下创建“popup”文件夹,用于存放弹出窗的代码。弹出窗由以下文件组成:</p>
+
+<ul>
+ <li><strong><code>choose_beast.html</code></strong> 定义了界面的主面板</li>
+ <li><strong><code>choose_beast.css</code></strong> 美化内容</li>
+ <li><strong><code>choose_beast.js</code></strong> 通过在当前活跃的标签页中运行内容脚本(content script)处理用户的选择</li>
+</ul>
+
+<pre class="brush: bash line-numbers language-bash"><code class="language-bash"><span class="function token">mkdir</span> popup
+<span class="function token">cd</span> popup
+<span class="function token">touch</span> choose_beast.html choose_beast.css choose_beast.js</code></pre>
+
+<h4 id="choose_beast.html">choose_beast.html</h4>
+
+<p>HTML 文件就像这样:</p>
+
+<ol>
+ <li>
+ <pre class="brush: html">&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;meta charset="utf-8"&gt;
+ &lt;link rel="stylesheet" href="choose_beast.css"/&gt;
+ &lt;/head&gt;
+
+&lt;body&gt;
+ &lt;div id="popup-content"&gt;
+ &lt;div class="button beast"&gt;Frog&lt;/div&gt;
+ &lt;div class="button beast"&gt;Turtle&lt;/div&gt;
+ &lt;div class="button beast"&gt;Snake&lt;/div&gt;
+ &lt;div class="button reset"&gt;Reset&lt;/div&gt;
+ &lt;/div&gt;
+ &lt;div id="error-content" class="hidden"&gt;
+ &lt;p&gt;Can't beastify this web page.&lt;/p&gt;&lt;p&gt;Try a different page.&lt;/p&gt;
+ &lt;/div&gt;
+ &lt;script src="choose_beast.js"&gt;&lt;/script&gt;
+&lt;/body&gt;
+
+&lt;/html&gt;</pre>
+ </li>
+</ol>
+
+<p>我们有一个ID为 <code>"popup-content"</code> 的<a href="/zh-CN/docs/Web/HTML/Element/div">&lt;div&gt;</a>元素包含了每个动物选择。我们还有另外一个<code>&lt;div&gt;</code> 元素,它的ID为 <code>"error-content"</code> ,class为<code>"hidden"</code>。我们将会使用它以防初始化弹窗的时候出问题。</p>
+
+<p>注意我们引入了CSS和JS文件,就像网页一样。</p>
+
+<h4 id="choose_beast.css">choose_beast.css</h4>
+
+<p>CSS 固定了弹出窗的大小,确保3个选择填充满空间,并给了他们基本点样式。同时隐藏了<code>class="hidden"</code>的元素,这意味着我们的<code>"error-content"</code> <code>&lt;div&gt;</code> 将会被默认隐藏:</p>
+
+<ol>
+ <li>
+ <pre class="brush: css">html, body {
+ width: 100px;
+}
+
+.hidden {
+ display: none;
+}
+
+.button {
+ margin: 3% auto;
+ padding: 4px;
+ text-align: center;
+ font-size: 1.5em;
+ cursor: pointer;
+}
+
+.beast:hover {
+ background-color: #CFF2F2;
+}
+
+.beast {
+ background-color: #E5F2F2;
+}
+
+.reset {
+ background-color: #FBFBC9;
+}
+
+.reset:hover {
+ background-color: #EAEA9D;
+}</pre>
+ </li>
+</ol>
+
+<h4 id="choose_beast.js">choose_beast.js</h4>
+
+<p>我们在弹出窗的脚本中监听点击事件。 如果用户选择其中一个动物,我们在当前标签页中插入一段内容脚本。一旦内容脚本加载,我们发送一条有关动物选择的信息:</p>
+
+<ol>
+ <li>
+ <pre class="brush: js">/**
+ * CSS to hide everything on the page,
+ * except for elements that have the "beastify-image" class.
+ */
+const hidePage = `body &gt; :not(.beastify-image) {
+ display: none;
+ }`;
+
+/**
+ * Listen for clicks on the buttons, and send the appropriate message to
+ * the content script in the page.
+ */
+function listenForClicks() {
+ document.addEventListener("click", (e) =&gt; {
+
+ /**
+ * Given the name of a beast, get the URL to the corresponding image.
+ */
+ function beastNameToURL(beastName) {
+ switch (beastName) {
+ case "Frog":
+ return browser.extension.getURL("beasts/frog.jpg");
+ case "Snake":
+ return browser.extension.getURL("beasts/snake.jpg");
+ case "Turtle":
+ return browser.extension.getURL("beasts/turtle.jpg");
+ }
+ }
+
+ /**
+ * Insert the page-hiding CSS into the active tab,
+ * then get the beast URL and
+ * send a "beastify" message to the content script in the active tab.
+ */
+ function beastify(tabs) {
+ browser.tabs.insertCSS({code: hidePage}).then(() =&gt; {
+ let url = beastNameToURL(e.target.textContent);
+ browser.tabs.sendMessage(tabs[0].id, {
+ command: "beastify",
+ beastURL: url
+ });
+ });
+ }
+
+ /**
+ * Remove the page-hiding CSS from the active tab,
+ * send a "reset" message to the content script in the active tab.
+ */
+ function reset(tabs) {
+ browser.tabs.removeCSS({code: hidePage}).then(() =&gt; {
+ browser.tabs.sendMessage(tabs[0].id, {
+ command: "reset",
+ });
+ });
+ }
+
+ /**
+ * Just log the error to the console.
+ */
+ function reportError(error) {
+ console.error(`Could not beastify: ${error}`);
+ }
+
+ /**
+ * Get the active tab,
+ * then call "beastify()" or "reset()" as appropriate.
+ */
+ if (e.target.classList.contains("beast")) {
+ browser.tabs.query({active: true, currentWindow: true})
+ .then(beastify)
+ .catch(reportError);
+ }
+ else if (e.target.classList.contains("reset")) {
+ browser.tabs.query({active: true, currentWindow: true})
+ .then(reset)
+ .catch(reportError);
+ }
+ });
+}
+
+/**
+ * There was an error executing the script.
+ * Display the popup's error message, and hide the normal UI.
+ */
+function reportExecuteScriptError(error) {
+ document.querySelector("#popup-content").classList.add("hidden");
+ document.querySelector("#error-content").classList.remove("hidden");
+ console.error(`Failed to execute beastify content script: ${error.message}`);
+}
+
+/**
+ * When the popup loads, inject a content script into the active tab,
+ * and add a click handler.
+ * If we couldn't inject the script, handle the error.
+ */
+browser.tabs.executeScript({file: "/content_scripts/beastify.js"})
+.then(listenForClicks)
+.catch(reportExecuteScriptError);</pre>
+ </li>
+</ol>
+
+<p>从96行开始。只要弹出窗加载完,popup scrpit 就会使用 <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript">browser.tabs.executeScript()</a></code> API在活跃标签页执行 content script。如果执行 content scrpit成功,content script会在页面中一直保持,直到标签被关闭或者用户导航到其他页面。</p>
+
+<p><code>browser.tabs.executeScript()</code>调用失败的常见原因是你不能在所有页面执行content scripts。例如,你不能在特权浏览器页面执行,像about:debugging,你也不能在<a href="https://addons.mozilla.org/">addons.mozilla.org</a>域执行。如果调用失败,<code>reportExecuteScriptError()</code>会隐藏<code>"popup-content"</code> <code>&lt;div&gt;</code>,并展示<code>"error-content"</code> <code>&lt;div&gt;</code>, 然后打印一个错误到<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Debugging">控制台</a>。</p>
+
+<p>如果成功执行 content script ,我们会调用 <code>listenForClicks()</code>。这个监听了弹窗上的点击事件。</p>
+
+<ul>
+ <li>如果点击有 <code>class="beast"</code>的按钮上,将会调用 <code>beastify()</code>.</li>
+ <li>如果点击有 <code>class="reset"</code>的按钮上,将会调用 <code>reset()</code>.</li>
+</ul>
+
+<p><code>beastify()</code> 函数做了三件事:</p>
+
+<ul>
+ <li>将被点击的按钮映射到一个指向特定动物图片的URL</li>
+ <li>通过<code><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/insertCSS">browser.tabs.insertCSS()</a></code> API 向页面注入一些CSS来隐藏整个页面的内容</li>
+ <li>通过<code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/sendMessage">browser.tabs.sendMessage()</a></code> API 向 content script 发送“beastify”信息,要求其 beastify 页面,同时向其传递一个指向动物图片的URL</li>
+</ul>
+
+<p><code>reset()</code> 函数实际上就是撤销 beastify :</p>
+
+<ul>
+ <li>通过 <code><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/removeCSS">browser.tabs.removeCSS()</a></code> API 移除我们添加的CSS</li>
+ <li>向 content script 发送“reset”信息要求其重置页面</li>
+</ul>
+
+<h3 id="The_content_script">The content script</h3>
+
+<p>在扩展的根目录下创建一个新的文件夹,叫做"content_scripts",然后在里面新建一个新的名为 "beastify.js" 的文件,内容如下:</p>
+
+<ol>
+ <li>
+ <pre class="brush: js">(function() {
+ /**
+ * Check and set a global guard variable.
+ * If this content script is injected into the same page again,
+ * it will do nothing next time.
+ */
+ if (window.hasRun) {
+ return;
+ }
+ window.hasRun = true;
+
+ /**
+ * Given a URL to a beast image, remove all existing beasts, then
+ * create and style an IMG node pointing to
+ * that image, then insert the node into the document.
+ */
+ function insertBeast(beastURL) {
+ removeExistingBeasts();
+ let beastImage = document.createElement("img");
+ beastImage.setAttribute("src", beastURL);
+ beastImage.style.height = "100vh";
+ beastImage.className = "beastify-image";
+ document.body.appendChild(beastImage);
+ }
+
+ /**
+ * Remove every beast from the page.
+ */
+ function removeExistingBeasts() {
+ let existingBeasts = document.querySelectorAll(".beastify-image");
+ for (let beast of existingBeasts) {
+ beast.remove();
+ }
+ }
+
+ /**
+ * Listen for messages from the background script.
+ * Call "beastify()" or "reset()".
+ */
+ browser.runtime.onMessage.addListener((message) =&gt; {
+ if (message.command === "beastify") {
+ insertBeast(message.beastURL);
+ } else if (message.command === "reset") {
+ removeExistingBeasts();
+ }
+ });
+
+})();</pre>
+ </li>
+</ol>
+
+<p>content script做的第一件事是检查全局变量 <code>window.hasRun</code>:如果它被设置了,脚本直接返回,否则设置<code>window.hasRun</code>并继续。原因是每次用户打开弹出窗,弹出窗就会在活跃页面执行一个content script ,所以我们可能会在单个页面运行多个脚本实例。如果是这样的话,我们需要保证只有一个实例在做所有事情。</p>
+
+<p>然后,从第40行开始,content script 监听来自弹出窗的信息,使用<code><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/runtime/onMessage">browser.runtime.onMessage</a></code> API。在上面我们看到弹出窗脚本能够发送两种不同的信息:"beastify" and "reset"。</p>
+
+<ul>
+ <li>如果信息是 "beastify",我们期待它包含一个指向动物图片的URL。我们移除先前调用添加的动物图片,然后构造并添加一个 src属性被设置动物图片URL 的<code><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img">&lt;img&gt;</a></code> 元素。</li>
+ <li>如果信息是 "reset",我们只需要移除所有被添加的动物片。</li>
+</ul>
+
+<h3 id="动物们">动物们</h3>
+
+<p>最后,我们要加入包含动物们的图像。</p>
+
+<p>创建"beasts"文件夹,之后将图片放入并命名。你可以从 <a href="https://github.com/mdn/webextensions-examples/tree/master/beastify/beasts">the GitHub repository</a>,或这里下载图片:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/11459/frog.jpg" style="display: inline-block; height: 200px; margin: 20px; width: 200px;"><img alt="" src="https://mdn.mozillademos.org/files/11461/snake.jpg" style="display: inline-block; height: 200px; margin: 20px; width: 200px;"><img alt="" src="https://mdn.mozillademos.org/files/11463/turtle.jpg" style="display: inline-block; height: 200px; margin: 20px; width: 200px;"></p>
+
+<h2 id="测试">测试</h2>
+
+<p>请仔细确认项目目录如下所示:</p>
+
+<ol>
+ <li>
+ <pre><code>beastify/
+
+ beasts/
+ frog.jpg
+ snake.jpg
+ turtle.jpg
+
+ content_scripts/
+ beastify.js
+
+ icons/
+ beasts-32.png
+ beasts-48.png
+
+ popup/
+ choose_beast.css
+ choose_beast.html
+ choose_beast.js
+
+ manifest.json</code></pre>
+ </li>
+</ol>
+
+<p>Firefox 45开始,你可以临时从硬盘中安装扩展</p>
+
+<p>在Firefox地址栏中输入:about:debugging,单击“临时载入附加组件”,然后选择你的manifest.json文件。</p>
+
+<p>然后你应该已经看到扩展图标出现在了Firefox的工具条上:</p>
+
+<p>{{EmbedYouTube("sAM78GU4P34")}}</p>
+
+<p>打开一个网页,然后点击图标,选择一个动物,然后观察网页的变化</p>
+
+<p>{{EmbedYouTube("YMQXyAQSiE8")}}</p>
+
+<h2 id="用命令行开发">用命令行开发</h2>
+
+<p>你可以通过使用 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Getting_started_with_web-ext">web-ext</a> 工具来将临时安装的工作自动化,试试这个:</p>
+
+<ol>
+ <li>
+ <pre class="brush: bash"><code>cd beastify
+web-ext run</code></pre>
+ </li>
+</ol>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/what_are_webextensions/index.html b/files/zh-cn/mozilla/add-ons/webextensions/what_are_webextensions/index.html
new file mode 100644
index 0000000000..d327d3bd6a
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/what_are_webextensions/index.html
@@ -0,0 +1,61 @@
+---
+title: 扩展是什么?
+slug: Mozilla/Add-ons/WebExtensions/What_are_WebExtensions
+tags:
+ - Add-ons
+ - WebExtensions
+ - 拓展
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/What_are_WebExtensions
+---
+<div>{{AddonSidebar}}</div>
+
+<p>扩展为浏览器添加特性与功能。它通过熟悉的 web 技术——HTML,CSS 还有 JavaScript 来创建。扩展可以利用网页上的 JavaScript 使用同一批 API,但扩展也可以访问扩展自己专用的 JavaScript API。这意味着,和在网页里编码相比,在扩展中,可以做到更加多的事情。以下是其中一些你可以做的事情的示例:</p>
+
+<p><strong>提升或补充网站功能:</strong>用扩展来实现额外的浏览器内的特性或者来自于你网站的信息。它允许用户搜集他们访问过的页面细节来提升你所提供的服务。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15808/Amazon_add_on.png"></p>
+
+<p>示例: <a href="https://addons.mozilla.org/zh-CN/firefox/addon/amazon-browser-bar/">亚马逊助手</a>, <a href="https://addons.mozilla.org/zh-CN/firefox/addon/onenote-clipper/">OneNote Web Clipper</a>, 和 <a href="https://addons.mozilla.org/zh-CN/firefox/addon/grammarly-1/">Grammarly for Firefox</a></p>
+
+<p><strong>让用户展现他们的个性:</strong>浏览器扩展可以操控网页的内容;例如,让用户在每个页面上添加他们最喜欢的徽标或者图片。扩展也可以让用户更新火狐浏览器的界面,就像独立的<a href="https://developer.mozilla.org/en-US/Add-ons/Themes/Theme_concepts">主题扩展</a>一样。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15809/MyWeb_New_Tab_add_on.png" style="height: 398px; width: 540px;"></p>
+
+<p>示例: <a href="https://addons.mozilla.org/zh-CN/firefox/addon/myweb-new-tab/">MyWeb New Tab</a>, <a href="https://addons.mozilla.org/zh-CN/firefox/addon/tabliss/">Tabliss</a>, 和 <a href="https://addons.mozilla.org/zh-CN/firefox/addon/vivaldifox/">VivaldiFox</a></p>
+
+<p><strong>从网页中添加或删除内容:</strong>你可能想要帮助用户从网页中阻止一些侵扰的广告,当网页中提到一个国家或者城市时提供旅游指南,或者重组页面内容来提供一个统一的阅读体验。有了可以访问和更新一个页面里的 HTML 和 CSS的能力,扩展可以帮助用户以他们想要的形式来查看网页。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15807/ublock_origin_add_on.png" style="height: 480px; width: 640px;"></p>
+
+<p>示例: <a href="https://addons.mozilla.org/zh-CN/firefox/addon/ublock-origin/">uBlock Origin</a>, <a href="https://addons.mozilla.org/zh-CN/firefox/addon/reader/">Reader</a>, 和 <a href="https://addons.mozilla.org/zh-CN/firefox/addon/toolbox-google-play-store/">Toolbox for Google Play Store™</a></p>
+
+<p><strong>添加工具和新的浏览特性:</strong>给任务面板添加新特性,或者从URL地址,超链接,或者页面文字生成二维码。有了灵活的界面选择和 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions">WebExtensions APIs</a> 你可以轻松的添加新的特性到浏览器。并且,你可以提升几乎任何网站的特性或者功能,不必是你自己的网站。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15806/QR_Code_Image_Generator_add_on.png"></p>
+
+<p>示例: <a href="https://addons.mozilla.org/zh-CN/firefox/addon/swimlanes-for-trello/">Swimlanes for Trello</a> 和 <a href="https://addons.mozilla.org/zh-CN/firefox/addon/tomato-clock/">Tomato Clock</a></p>
+
+<p><strong>游戏:</strong>通过线下游戏的特性,或者探索新游戏的可能性来提供传统计算机游戏功能;例如,把游戏合并入每天网页浏览中。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15805/Asteroids_in_Popup_add_on%20.png" style="height: 438px; width: 700px;"></p>
+
+<p>示例:<a href="https://addons.mozilla.org/zh-CN/firefox/addon/solitaire-card-game-new-tab/">Solitaire Card Game New Tab</a>, 和 <a href="https://addons.mozilla.org/zh-CN/firefox/addon/2048-prime/">2048 Prime</a>.</p>
+
+<p><strong>添加开发工具:</strong>你可以提供网站开发工具给你的公司或者开发一个有用的技术或者你想分享的网站开发技术。无论哪种方式,你可以通过对开发者工具栏添加一个新的标齐那也来提升内置的 Firefox 开发者工具。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/15804/aXe_Developer_Tools_add_on.png" style="height: 261px; width: 700px;"></p>
+
+<p>示例: <a href="https://addons.mozilla.org/zh-CN/firefox/addon/web-developer/">Web Developer</a>, <a href="https://addons.mozilla.org/zh-CN/firefox/addon/react-devtools/">Web React Developer Tools</a>, 和 <a href="https://addons.mozilla.org/zh-CN/firefox/addon/axe-devtools/">aXe Developer Tools</a></p>
+
+<p>Firefox 扩展使用 WebExtensions API,一种跨浏览器的扩展开发系统,构建而成。 在很大程度上,它与 Google Chrome 和 Opera 所支持的<a class="external-icon external" href="https://developer.chrome.com/extensions">扩展 API</a> 兼容。 在大多数情况下,为这些浏览器所写的扩展只需<a href="/zh-CN/Add-ons/WebExtensions/Porting_from_Google_Chrome">少量修改</a>便可在 FireFox 和 Microsoft Edge 上运行。这些 API 也完全兼容<a href="/zh-CN/Firefox/Multiprocess_Firefox">多线程 Firefox</a>。</p>
+
+<p>如果你有想法或问题,或者在使用 WebExtensions API 迁移旧式附加组件时需要帮助,您可以在 <a class="external-icon external" href="https://mail.mozilla.org/listinfo/dev-addons">dev-addons 邮件列表</a>或者<a class="external-icon external" href="https://wiki.mozilla.org/Matrix">Matrix</a> 上的 <a href="https://chat.mozilla.org/#/room/#addons:mozilla.org">Add-ons room</a> 与我们联系。</p>
+
+<h2 id="接下来呢?">接下来呢?</h2>
+
+<ul>
+ <li>在<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension">你的第一个扩展</a>中开始开发一个简单的扩展。</li>
+ <li>在<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Anatomy_of_a_WebExtension">解析一个扩展</a>中了解扩展的结构。</li>
+ <li>在<a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Examples">扩展示例</a>中尝试一些示例扩展。</li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/what_next_/index.html b/files/zh-cn/mozilla/add-ons/webextensions/what_next_/index.html
new file mode 100644
index 0000000000..91694acf8d
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/what_next_/index.html
@@ -0,0 +1,58 @@
+---
+title: What next?
+slug: Mozilla/Add-ons/WebExtensions/What_next_
+translation_of: Mozilla/Add-ons/WebExtensions/What_next_
+---
+<div>{{AddonSidebar}}</div>
+
+<p>You will now be ready to start turning your idea for a browser extension into reality. Before you start that journey, it's worth being aware of a few things that will help to make it a smooth one.</p>
+
+<h2 id="你的开发环境">你的开发环境</h2>
+
+<p>你不需要任何特殊的开发或构建环境工具来创建浏览器扩展:只需要一个简单的文本编辑器就可以创建出很好的浏览器扩展。当然,你可能一直在做web开发有一套你想去配置的开发工具和环境。如果是这样,你需要意识到一些事情。</p>
+
+<p>如果你使用了打包压缩工具来交付你最终的代码,你需要提交你的源码到<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/What_next_$translate?tolocale=zh-CN#The_review_process"> AMO </a>审查。此外,用于压缩、混淆、构建的工具需要是开源的(或提供无限的免费使用), 并且可以在审阅者的计算机(Windows、Mac或Linux)上运行。主要是,我们的审阅者无法使用商业或基于Web的工具。</p>
+
+<p> </p>
+
+<p><a href="/en-US/Add-ons/Source_Code_Submission#About_build_tools">学习更多关于构建工具</a></p>
+
+<h2 id="Third-party_libraries">Third-party libraries</h2>
+
+<p>Third-party libraries are a great way to add complex features or functionality to your browser extensions quickly. When you submit an extension to the <a href="#The_review_processv">AMO review process</a>, the process will also consider any third-party libraries used. To streamline the review, make sure you always download third-party libraries from their official website or repository, and if the library is minified provide a link to the source code. Please note that third-party libraries cannot be modified in any way.</p>
+
+<p><a href="/en-US/Add-ons/Source_Code_Submission">Learn more about submitting source code</a></p>
+
+<h2 id="The_Firefox_Add-on_Distribution_Agreement">The Firefox Add-on Distribution Agreement</h2>
+
+<p>Browser extensions need to be signed to install into the release or beta versions of Firefox. Signing takes place in addons.mozilla.org (AMO) and is subject to the terms and conditions of the Firefox Add-on Distribution Agreement. The goal of the agreement is to ensure Firefox users get access to well supported, quality add-ons that enhance the Firefox experience.</p>
+
+<p><a href="/Add-ons/AMO/Policy/Agreement">Read the agreement</a></p>
+
+<p><a href="/en-US/Add-ons/WebExtensions/Distribution">Learn more about signing</a></p>
+
+<h2 id="The_review_process">The review process</h2>
+
+<p>When a browser extension is submitted for signing, it's subject to automated review. It may also be subject to a manual review, when the automated review determines that a manual review is needed. Your browser extension won't be signed until it’s passed the automated review and may have its signing revoked if it fails to pass the manual review. The review process follows a strict set of guidelines, so it’s easy to check and avoid any likely review problems.</p>
+
+<p><a href="/en-US/Add-ons/AMO/Policy/Reviews">Check out the review policy and guidelines</a></p>
+
+<h2 id="AMO_featured_browser_extensions">AMO featured browser extensions</h2>
+
+<p>If you choose to list your browser extension on AMO, your extension could be featured on the AMO website, in the Firefox browser’s add-on manager, or elsewhere on a Mozilla website. We've compiled a list of guidelines about how extensions are selected for featuring, by following these guidelines you give your extension the best chance of being featured.</p>
+
+<p><a href="/en-US/Add-ons/AMO/Policy/Featured">Learn more about getting your add-ons featured</a></p>
+
+<h2 id="Continue_your_learning_experience">Continue your learning experience</h2>
+
+<p>Now you know what lies ahead, it's time to dive into more details about browser extension development. In the sections that follow, you’ll discover:</p>
+
+<ul>
+ <li>More about the fundamental concepts behind browser extensions, starting with details on how to <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Using_the_JavaScript_APIs">use the JavaScript APIs</a>.</li>
+ <li>A guide to the <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface">user interface components</a> available to your browser extensions.</li>
+ <li>A collection of how-to guides on achieving key tasks in your extensions or making use of the JavaScript APIs.</li>
+ <li>Information on how to port other browser extensions to Firefox.</li>
+ <li>Details about the Firefox specific workflows you can use to develop browser extensions.</li>
+ <li>A full reference guide to the JavaScript APIs.</li>
+ <li>A full reference guide to the Manifest keys.</li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/working_with_the_tabs_api/index.html b/files/zh-cn/mozilla/add-ons/webextensions/working_with_the_tabs_api/index.html
new file mode 100644
index 0000000000..e1b5878010
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/working_with_the_tabs_api/index.html
@@ -0,0 +1,634 @@
+---
+title: Working with the Tabs API
+slug: Mozilla/Add-ons/WebExtensions/Working_with_the_Tabs_API
+tags:
+ - 选项卡
+ - 附加组件
+translation_of: Mozilla/Add-ons/WebExtensions/Working_with_the_Tabs_API
+---
+<p>{{AddonSidebar}}</p>
+
+<p><span class="tlid-translation translation" lang="zh-CN"><span title="">选项卡允许用户在其浏览器窗口中打开多个网页,然后在这些网页之间切换。</span> <span title="">使用Tabs API,您可以使用和操作这些选项卡来创建实用程序,为用户提供使用选项卡或提供扩展功能的新方法。</span></span></p>
+
+<p>在这篇how-to文章中我们将看到:</p>
+
+<ul>
+ <li><span class="tlid-translation translation" lang="zh-CN"><span title="">使用Tabs API所需的权限。</span></span></li>
+ <li><span class="tlid-translation translation" lang="zh-CN"><span title="">使用{{WebExtAPIRef("tabs.query")}}发现有关标签及其属性的更多信息。</span></span></li>
+ <li><span class="tlid-translation translation" lang="zh-CN"><span title="">创建、复制、移动、更新、重新加载和删除选项卡。</span></span></li>
+ <li><span class="tlid-translation translation" lang="zh-CN"><span title="">操纵标签的缩放大小。</span></span></li>
+ <li><span class="tlid-translation translation" lang="zh-CN"><span title="">操纵选项卡的CSS。</span></span></li>
+</ul>
+
+<p><span class="tlid-translation translation" lang="zh-CN"><span title="">最后,我们通过查看API提供的其他一些其他功能。</span></span></p>
+
+<div class="blockIndicator note">
+<p><span class="tlid-translation translation" lang="zh-CN"><span title="">注意:其他地方有一些Tab API功能。</span> <span title="">这些是可用于使用脚本操作选项卡内容的方法{{WebExtAPIRef("tabs.connect")}},{{WebExtAPIRef("tabs.sendMessage")}}和{{WebExtAPIRef("tabs.executeScript")}}</span>。<span title="">如果您需要有关这些方法的更多信息,请参阅概念文章<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts">内容脚本</a>和操作指南<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Modify_a_web_page">修改网页</a>。</span></span></p>
+</div>
+
+<h2 id="权限和选项卡API"><span class="tlid-translation translation" lang="zh-CN"><span title="">权限和选项卡API</span></span></h2>
+
+<p><span class="tlid-translation translation" lang="zh-CN"><span title="">对于大多数Tabs API函数,您不需要任何权限;</span> <span title="">但是,有一些例外:</span></span></p>
+
+<ul>
+ <li><span class="tlid-translation translation" lang="zh-CN"><span title="">需要</span></span><code>"tabs"</code><span class="tlid-translation translation" lang="zh-CN"><span title="">权限才能访问Tab对象的<code>Tab.url</code>,<code>Tab.title</code>和<code>Tab.favIconUrl</code>属性。</span> <span title="">在Firefox中,您还需要</span></span><code>"tabs"</code><span class="tlid-translation translation" lang="zh-CN"><span title="">来按URL执行<a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/query">查询</a>。</span></span></li>
+ <li>{{WebExtAPIRef("tabs.executeScript")}}或{{WebExtAPIRef("tabs.insertCSS")}}需要<a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">主机权限</a>。</li>
+</ul>
+
+<p>以下是您可以在扩展程序的manifest.json文件中请求<code>"tabs"</code>权限的方法:</p>
+
+<pre class="brush: json">"permissions": [
+  "&lt;all_urls&gt;",
+  "tabs"
+],
+</pre>
+
+<p>此请求允许您在用户访问的所有网站上使用所有标签API功能。 还有一种替代方法可以请求权限使用{{WebExtAPIRef("tabs.executeScript")}}或{{WebExtAPIRef("tabs.insertCSS")}},其中您不需要主机权限,形式为<a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission"><code>"activeTab"</code></a>。 此权限与<code>&lt;all_urls&gt;</code>提供与<code>"tabs"</code>相同的权限,但有两个限制:</p>
+
+<ul>
+ <li><span class="tlid-translation translation" lang="zh-CN"><span title="">用户必须通过其浏览器或页面操作,上下文菜单或快捷键与扩展进行交互。</span></span></li>
+ <li><span class="tlid-translation translation" lang="zh-CN"><span title="">它仅在活动选项卡中授予权限。</span></span></li>
+</ul>
+
+<p><span class="tlid-translation translation" lang="zh-CN"><span title="">这种方法的好处是用户不会收到权限警告,也就是说您的扩展程序可以“访问所有网站的数据”。</span> <span title="">这是因为</span></span><code>&lt;all_urls&gt;</code><span class="tlid-translation translation" lang="zh-CN"><span title="">权限使扩展能够在任何选项卡中随时执行脚本,而</span></span><a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#activeTab_permission"><code>"activeTab"</code></a><span class="tlid-translation translation" lang="zh-CN"><span title="">仅限于允许扩展在当前选项卡中执行用户请求的操作。</span></span></p>
+
+<h2 id="Discovering_more_about_tabs_and_their_properties">Discovering more about tabs and their properties</h2>
+
+<p>There will be occasions when you want to get a list of all the tabs in all the browser windows. Other times you might want to find a subset of tabs that match some specific criteria, such as those opened from a specific tab or displaying pages from a particular domain. And once you have your list of tabs, you’ll probably want to know more about their properties.</p>
+
+<p>This is where {{WebExtAPIRef("tabs.query")}} comes in. Used alone to get all tabs or taking the <code>queryInfo</code> object—to specify query criteria such as whether the tab is active, in the current window, or one or more of 17 criteria—{{WebExtAPIRef("tabs.query")}} returns an array of {{WebExtAPIRef("tabs.Tab")}} objects containing information about the tabs.</p>
+
+<p>Where you want information about the current tab only, you can get a {{WebExtAPIRef("tabs.Tab")}} object for that tab using {{WebExtAPIRef("tabs.getCurrent")}}. If you have a tab’s ID, you can get its {{WebExtAPIRef("tabs.Tab")}} object using {{WebExtAPIRef("tabs.get")}}.</p>
+
+<div class="blockIndicator note">
+<p><strong>Note:</strong></p>
+
+<ul>
+ <li><strong>In Chrome,</strong> the user can select multiple tabs in a window, and the Tabs API sees these as highlighted tabs.</li>
+ <li><strong>In Firefox,</strong> the user can’t select multiple tabs, so “highlighted” and “active” are synonymous.</li>
+</ul>
+</div>
+
+<h3 id="How_to_example">How to example</h3>
+
+<p>To see how {{WebExtAPIRef("tabs.query")}} and {{WebExtAPIRef("tabs.Tab")}} are used, let’s walk through how the <a href="https://github.com/mdn/webextensions-examples/tree/master/tabs-tabs-tabs">tabs-tabs-tabs</a> example adds the list of “switch to tabs” to its toolbar button popup.</p>
+
+<p><img alt="The tabs tabs tabs toolbar menu showing the switch to tap area" src="https://mdn.mozillademos.org/files/15723/Switch_to_tab.png" style="height: 645px; width: 369px;"></p>
+
+<h3 id="manifest.json">manifest.json</h3>
+
+<p>Here is the <a href="https://github.com/mdn/webextensions-examples/blob/master/tabs-tabs-tabs/manifest.json">manifest.json</a>:</p>
+
+<pre class="brush: json">{
+  "browser_action": {
+    "browser_style": true,
+    "default_title": "Tabs, tabs, tabs",
+    "default_popup": "tabs.html"
+  },
+  "description": "A list of methods you can perform on a tab.",
+  "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/tabs-tabs-tabs",
+  "manifest_version": 2,
+  "name": "Tabs, tabs, tabs",
+  "permissions": [
+    "tabs"
+  ],
+  "version": "1.0"
+}
+</pre>
+
+<div class="blockIndicator note">
+<p>Note the following:</p>
+
+<ul>
+ <li>
+ <p><strong>tabs.html is defined as the <code>default_popup</code> in <code>browser_action</code>.</strong> It is displayed whenever the user clicks the extension’s toolbar icon.</p>
+ </li>
+ <li>
+ <p><strong>Permissions includes tabs.</strong> This is needed to support the tab list feature, as the extension reads the title of the tabs for display in the popup.</p>
+ </li>
+</ul>
+</div>
+
+<h3 id="tabs.html">tabs.html</h3>
+
+<p>tabs.html defines the content of the extension’s popup:</p>
+
+<pre class="brush: html">&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+
+ &lt;head&gt;
+    &lt;meta charset="utf-8"&gt;
+    &lt;link rel="stylesheet" href="tabs.css"/&gt;
+ &lt;/head&gt;
+
+&lt;body&gt;
+
+ &lt;div class="panel"&gt;
+    &lt;div class="panel-section panel-section-header"&gt;
+     &lt;div class="text-section-header"&gt;Tabs-tabs-tabs&lt;/div&gt;
+    &lt;/div&gt;
+
+    &lt;a href="#" id="tabs-move-beginning"&gt;Move active tab to the beginning of the window&lt;/a&gt;&lt;br&gt;
+
+
+…
+
+Define the other menu items
+…
+
+    &lt;div class="switch-tabs"&gt;
+
+     &lt;p&gt;Switch to tab&lt;/p&gt;
+
+     &lt;div id="tabs-list"&gt;&lt;/div&gt;
+
+    &lt;/div&gt;
+ &lt;/div&gt;
+
+ &lt;script src="tabs.js"&gt;&lt;/script&gt;
+
+&lt;/body&gt;
+
+&lt;/html&gt;
+</pre>
+
+<p>Here is a summary of the above does:</p>
+
+<ol>
+ <li>The menu items are declared.  </li>
+ <li>An empty <code>div</code> with the ID <code>tabs-list</code> is declared to contain the list of tabs.</li>
+ <li>tabs.js is called.</li>
+</ol>
+
+<h3 id="tabs.js">tabs.js</h3>
+
+<p>In <a href="https://github.com/mdn/webextensions-examples/blob/master/tabs-tabs-tabs/tabs.js">tabs.js</a>, we’ll see how the list of tabs is built and added to the popup.  </p>
+
+<h4 id="Creating_the_popup">Creating the popup</h4>
+
+<p>First, an event handler is added to execute <code>listTabs()</code> when tabs.html is loaded:</p>
+
+<pre class="brush: js">document.addEventListener("DOMContentLoaded", listTabs);</pre>
+
+<p>The first thing that <code>listTabs()</code> does is to call <code>getCurrentWindowTabs()</code>. This is where {{WebExtAPIRef("tabs.query")}} is used to get a {{WebExtAPIRef("tabs.Tab")}} object for the tabs in the current window:</p>
+
+<pre class="brush: js">function getCurrentWindowTabs() {
+  return browser.tabs.query({currentWindow: true});
+}
+</pre>
+
+<p>Now, <code>listTabs()</code> is ready to create the content for the popup.</p>
+
+<p>To start with:</p>
+
+<ol>
+ <li>Grab the <code>tabs-list</code> <code>div</code>.</li>
+ <li>Create a document fragment (into which the list will be built).</li>
+ <li>Set counters.</li>
+ <li>Clear the content of the <code>tabs-list</code> <code>div</code>.</li>
+</ol>
+
+<pre class="brush: js">function listTabs() {
+ getCurrentWindowTabs().then((tabs) =&gt; {
+    let tabsList = document.getElementById('tabs-list');
+    let currentTabs = document.createDocumentFragment();
+    let limit = 5;
+    let counter = 0;
+
+    tabsList.textContent = '';
+</pre>
+
+<p>Next, we’ll create the links for each tab:</p>
+
+<ol>
+ <li>Loops through the first 5 items from the {{WebExtAPIRef("tabs.Tab")}} object.</li>
+ <li>For each item, add a hyperlink to the document fragment.
+ <ul>
+ <li>The link’s label—that is, its text—is set using the tab’s title (or the ID, if it has no title).</li>
+ <li>The link’s address is set using the tab’s ID.</li>
+ </ul>
+ </li>
+</ol>
+
+<pre class="brush: js">    for (let tab of tabs) {
+     if (!tab.active &amp;&amp; counter &lt;= limit) {
+        let tabLink = document.createElement('a');
+
+        tabLink.textContent = tab.title || tab.id;
+
+       tabLink.setAttribute('href', tab.id);
+        tabLink.classList.add('switch-tabs');
+        currentTabs.appendChild(tabLink);
+     }
+
+     counter += 1;
+
+    }
+</pre>
+
+<p>Finally, the document fragment is written to the <code>tabs-list</code> div:</p>
+
+<pre class="brush: js">    tabsList.appendChild(currentTabs);
+  });
+}
+</pre>
+
+<h4 id="Working_with_the_active_tab">Working with the active tab</h4>
+
+<p>Another related example feature is the “Alert active tab” info option that dumps all the {{WebExtAPIRef("tabs.Tab")}} object properties for the active tab into an alert:</p>
+
+<pre class="brush: js"> else if (e.target.id === "tabs-alertinfo") {
+   callOnActiveTab((tab) =&gt; {
+     let props = "";
+     for (let item in tab) {
+       props += `${ item } = ${ tab[item] } \n`;
+     }
+     alert(props);
+   });
+ }
+</pre>
+
+<p>Where <code>callOnActiveTab()</code> finds the active tab object by looping through the {{WebExtAPIRef("tabs.Tab")}} objects looking for the item with active set:</p>
+
+<pre class="brush: js">document.addEventListener("click", function(e) {
+ function callOnActiveTab(callback) {
+   getCurrentWindowTabs().then((tabs) =&gt; {
+     for (var tab of tabs) {
+       if (tab.active) {
+         callback(tab, tabs);
+       }
+     }
+   });
+ }
+}
+
+</pre>
+
+<h2 id="Creating_duplicating_moving_updating_reloading_and_removing_tabs">Creating, duplicating, moving, updating, reloading, and removing tabs</h2>
+
+<p>Having gathered information about the tabs you’ll most likely want to do something with them—either to offer users features for manipulating and managing tabs or to implement functionality in your extension.</p>
+
+<p>The following functions are available:</p>
+
+<ul>
+ <li>create a new tab ({{WebExtAPIRef("tabs.create")}}).</li>
+ <li>duplicate a tab ({{WebExtAPIRef("tabs.duplicate")}}).</li>
+ <li>remove a tab ({{WebExtAPIRef("tabs.remove")}}).</li>
+ <li>move a tab ({{WebExtAPIRef("tabs.move")}}).</li>
+ <li>update the tab’s URL—effectively browse to a new page—({{WebExtAPIRef("tabs.update")}}).</li>
+ <li>reload the tab’s page ({{WebExtAPIRef("tabs.reload")}}).</li>
+</ul>
+
+<div class="blockIndicator note">
+<p><strong>NOTE: </strong></p>
+
+<p>These functions all require the ID (or IDs) of the tab they are manipulating:</p>
+
+<ul>
+ <li>{{WebExtAPIRef("tabs.duplicate")}}</li>
+ <li>{{WebExtAPIRef("tabs.remove")}}</li>
+ <li>{{WebExtAPIRef("tabs.move")}}</li>
+</ul>
+
+<p>Whereas the following functions will act on the active tab (if no tab ID is provided): </p>
+
+<ul>
+ <li>{{WebExtAPIRef("tabs.update")}}</li>
+ <li>{{WebExtAPIRef("tabs.reload")}}</li>
+</ul>
+</div>
+
+<h3 id="How_to_example_2">How to example</h3>
+
+<p>The <a href="https://github.com/mdn/webextensions-examples/tree/master/tabs-tabs-tabs">tabs-tabs-tabs</a> example exercises all of these features except for updating a tab’s URL The way in which these APIs are used is similar, so we’ll look at one of the more involved implementations, that of the “Move active tab to the beginning of the window list” option.</p>
+
+<p>But first, here is a demonstration of the feature in action:</p>
+
+<p>{{EmbedYouTube("-lJRzTIvhxo")}}</p>
+
+<h4 id="manifest.json_2"><a href="https://github.com/mdn/webextensions-examples/blob/master/tabs-tabs-tabs/manifest.json">manifest.json</a></h4>
+
+<p>None of the functions require a permission to operate, so there are no features in the manifest.json file that need to be highlighted.</p>
+
+<h4 id="tabs.html_2"><a href="https://github.com/mdn/webextensions-examples/blob/master/tabs-tabs-tabs/tabs.html">tabs.html</a></h4>
+
+<p>tabs.html defines the “menu” displayed in the popup, which includes the “Move active tab to the beginning of the window list” option, with a series of <code>&lt;a&gt;</code> tags grouped by a visual separator. Each menu item is given an ID, which is used in tabs.js to determine which menu item is being requested.</p>
+
+<pre class="brush: html">    &lt;a href="#" id="tabs-move-beginning"&gt;Move active tab to the beginning of the window&lt;/a&gt;&lt;br&gt;
+    &lt;a href="#" id="tabs-move-end"&gt;Move active tab to the end of the window&lt;/a&gt;&lt;br&gt;
+
+    &lt;div class="panel-section-separator"&gt;&lt;/div&gt;
+
+
+    &lt;a href="#" id="tabs-duplicate"&gt;Duplicate active tab&lt;/a&gt;&lt;br&gt;
+
+    &lt;a href="#" id="tabs-reload"&gt;Reload active tab&lt;/a&gt;&lt;br&gt;
+    &lt;a href="#" id="tabs-alertinfo"&gt;Alert active tab info&lt;/a&gt;&lt;br&gt;</pre>
+
+<h4 id="tabs.js_2"><a href="https://github.com/mdn/webextensions-examples/blob/master/tabs-tabs-tabs/tabs.js">tabs.js</a></h4>
+
+<p>To implement the “menu” defined in tabs.html, tabs.js includes a listener for clicks in tabs.html:</p>
+
+<pre class="brush: js">document.addEventListener("click", function(e) {
+ function callOnActiveTab(callback) {
+
+   getCurrentWindowTabs().then((tabs) =&gt; {
+     for (var tab of tabs) {
+       if (tab.active) {
+         callback(tab, tabs);
+       }
+     }
+   });
+}
+}
+</pre>
+
+<p>A series of <code>if</code> statements then look to match the ID of the item clicked.</p>
+
+<p>This code snippet is for the “Move active tab to the beginning of the window list” option:</p>
+
+<pre class="brush: js"> if (e.target.id === "tabs-move-beginning") {
+   callOnActiveTab((tab, tabs) =&gt; {
+     var index = 0;
+     if (!tab.pinned) {
+       index = firstUnpinnedTab(tabs);
+     }
+     console.log(`moving ${tab.id} to ${index}`)
+     browser.tabs.move([tab.id], {index});
+   });
+ }
+</pre>
+
+<p>It's worth noting the use of <code>console.log()</code>. This enables you to output information to the <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/Debugging">debugger</a> console, which can be useful when resolving issues found during development.</p>
+
+<p><img alt="Example of the console.log output, from the move tabs feature, in the debugging console" src="https://mdn.mozillademos.org/files/15722/console.png" style="height: 329px; width: 911px;"></p>
+
+<p>The move code first calls <code>callOnActiveTab()</code> which in turn calls <code>getCurrentWindowTabs()</code> to get a {{WebExtAPIRef("tabs.Tab")}} object containing the active window’s tabs. It then loops through the object to find and return the active tab object:</p>
+
+<pre class="brush: js"> function callOnActiveTab(callback) {
+   getCurrentWindowTabs().then((tabs) =&gt; {
+     for (var tab of tabs) {
+       if (tab.active) {
+         callback(tab, tabs);
+       }
+     }
+   });
+ }
+</pre>
+
+<h5 id="Pinned_tabs">Pinned tabs</h5>
+
+<p>A feature of tabs is that the user can <dfn>pin</dfn> tabs in a window. Pinned tabs are placed at the start of the tab list and cannot be moved. This means that the earliest position a tab can move to is the first position after any pinned tabs. So, <code>firstUnpinnedTab()</code> is called to find the position of the first unpinned tab by looping through the <code>tabs</code> object:</p>
+
+<pre class="brush: js">function firstUnpinnedTab(tabs) {
+ for (var tab of tabs) {
+   if (!tab.pinned) {
+     return tab.index;
+   }
+ }
+}
+</pre>
+
+<p>We now have everything needed to move the tab: the active tab object from which we can get the tab ID and the position the tab is to be moved to. So, we can implement the move:</p>
+
+<pre class="brush: js">     browser.tabs.move([tab.id], {index});</pre>
+
+<p>The remaining functions to duplicate, reload, create, and remove tabs are implemented similarly.</p>
+
+<h2 id="Manipulating_a_tab’s_zoom_level">Manipulating a tab’s zoom level</h2>
+
+<p>The next set of functions enable you to get ({{WebExtAPIRef("tabs.getZoom")}}) and set ({{WebExtAPIRef("tabs.setZoom")}}) the zoom level within a tab. You can also retrieve the zoom settings ({{WebExtAPIRef("tabs.getZoomSettings")}}) but, at the time of writing, the ability to set the settings ({{WebExtAPIRef("tabs.setZoomSettings")}}) wasn’t available in Firefox.</p>
+
+<p>The level of zoom can be between 30% and 300% (represented as decimals <code>0.3</code> to <code>3</code>).</p>
+
+<p>In Firefox the default zoom settings are:</p>
+
+<ul>
+ <li><strong>default zoom level: </strong>100%.</li>
+ <li><strong>zoom mode:</strong> automatic (so the browser manages how zoom levels are set).</li>
+ <li><strong>scope of zoom changes:</strong> <code>"per-origin"</code>, meaning that when you visit a site again, it takes the zoom level set in your last visit.</li>
+</ul>
+
+<h3 id="How_to_example_3">How to example</h3>
+
+<p>The <a href="https://github.com/mdn/webextensions-examples/tree/master/tabs-tabs-tabs">tabs-tabs-tabs</a> example includes three demonstrations of the zoom feature: zoom in, zoom out, and reset zoom. Here is the feature in action:</p>
+
+<p>{{EmbedYouTube("RFr3oYBCg28")}}</p>
+
+<p>Let’s take a look at how the zoom in is implemented.</p>
+
+<h4 id="manifest.json_3"><a href="https://github.com/mdn/webextensions-examples/blob/master/tabs-tabs-tabs/manifest.json">manifest.json</a></h4>
+
+<p>None of the zoom functions require permissions, so there are no features in the manifest.json file that need to be highlighted.</p>
+
+<h4 id="tabs.html_3"><a href="https://github.com/mdn/webextensions-examples/blob/master/tabs-tabs-tabs/tabs.html">tabs.html</a></h4>
+
+<p>We have already discussed how the tabs.html defines the options for this extension, nothing new or unique is done to provide the zoom options.</p>
+
+<h4 id="tabs.js_3"><a href="https://github.com/mdn/webextensions-examples/blob/master/tabs-tabs-tabs/tabs.js">tabs.js</a></h4>
+
+<p>tabs.js starts by defining several constants used in the zoom code:</p>
+
+<pre class="brush: js">const ZOOM_INCREMENT = 0.2;
+const MAX_ZOOM = 3;
+const MIN_ZOOM = 0.3;
+const DEFAULT_ZOOM = 1;
+</pre>
+
+<p>It then uses the same listener we discussed earlier so it can act on clicks in tabs.html.</p>
+
+<p>For the zoom in feature, this runs:</p>
+
+<pre class="brush: js"> else if (e.target.id === "tabs-add-zoom") {
+   callOnActiveTab((tab) =&gt; {
+     var gettingZoom = browser.tabs.getZoom(tab.id);
+     gettingZoom.then((zoomFactor) =&gt; {
+       //the maximum zoomFactor is 3, it can't go higher
+       if (zoomFactor &gt;= MAX_ZOOM) {
+         alert("Tab zoom factor is already at max!");
+       } else {
+         var newZoomFactor = zoomFactor + ZOOM_INCREMENT;
+         //if the newZoomFactor is set to higher than the max accepted
+         //it won't change, and will never alert that it's at maximum
+         newZoomFactor = newZoomFactor &gt; MAX_ZOOM ? MAX_ZOOM : newZoomFactor;
+         browser.tabs.setZoom(tab.id, newZoomFactor);
+       }
+     });
+   });
+ }
+</pre>
+
+<p>This code uses <code>callOnActiveTab()</code> to get the details of the active tab, then {{WebExtAPIRef("tabs.getZoom")}} gets the tab’s current zoom factor. The current zoom is compared to the defined maximum (<code>MAX_ZOOM</code>) and an alert issued if the tab is already at the maximum zoom. Otherwise, the zoom level is incremented but limited to the maximum zoom, then the zoom is set with {{WebExtAPIRef("tabs.getZoom")}}.</p>
+
+<h2 id="Manipulating_a_tab’s_CSS">Manipulating a tab’s CSS</h2>
+
+<p>Another significant capability offered by the Tabs API is the ability to manipulate the CSS within a tab—add new CSS to a tab ({{WebExtAPIRef("tabs.insertCSS")}}) or remove CSS from a tab ({{WebExtAPIRef("tabs.removeCSS")}}).</p>
+
+<p>This can be useful, for example, if you want to highlight certain page elements or change the default layout of the page.</p>
+
+<h3 id="How_to_example_4">How to example</h3>
+
+<p>The <a href="https://github.com/mdn/webextensions-examples/tree/master/apply-css">apply-css</a> example uses these features to add a red border to the web page in the active tab. Here is the feature in action:</p>
+
+<p>{{EmbedYouTube("bcK-GT2Dyhs")}}</p>
+
+<p>Let’s walk through how it’s set up.</p>
+
+<h4 id="manifest.json_4"><a href="https://github.com/mdn/webextensions-examples/blob/master/apply-css/manifest.json">manifest.json</a></h4>
+
+<p>To use the CSS features you need either:</p>
+
+<ul>
+ <li><code>"tabs"</code> permission and <a href="/en-US/Add-ons/WebExtensions/manifest.json/permissions#Host_permissions">host permission</a> or</li>
+ <li><code>"activeTab"</code> permission.</li>
+</ul>
+
+<p>The latter is the most useful, as it allows an extension to use {{WebExtAPIRef("tabs.insertCSS")}} and {{WebExtAPIRef("tabs.removeCSS")}} in the active tab when run from the extension’s browser or page action, context menu, or a shortcut.</p>
+
+<pre class="brush: json">{
+  "description": "Adds a page action to toggle applying CSS to pages.",
+
+ "manifest_version": 2,
+ "name": "apply-css",
+ "version": "1.0",
+ "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/apply-css",
+
+ "background": {
+
+    "scripts": ["background.js"]
+ },
+
+ "page_action": {
+
+    "default_icon": "icons/off.svg",
+    "browser_style": true
+ },
+
+ "permissions": [
+    "activeTab",
+    "tabs"
+ ]
+
+}
+</pre>
+
+<p>You will note that <code>"tabs"</code> permission is requested in addition to <code>"activeTab"</code>. This additional permission is needed to enable the extension’s script to access the tab’s URL, the importance of which we’ll see in a moment.</p>
+
+<p>The other main features in the manifest.json file are the definition of:</p>
+
+<ul>
+ <li><strong>a background script</strong>, which starts running as soon as the extension is loaded.</li>
+ <li><strong>a “page action”</strong>, which defines an icon to be added to the browser’s address bar.</li>
+</ul>
+
+<h4 id="background.js"><a href="https://github.com/mdn/webextensions-examples/blob/master/apply-css/background.js">background.js</a></h4>
+
+<p>On startup, background.js sets some constants to define the CSS to be applied, titles for the “page action”, and a list of protocols the extension will work in:</p>
+
+<pre class="brush: js">const CSS = "body { border: 20px solid red; }";
+const TITLE_APPLY = "Apply CSS";
+const TITLE_REMOVE = "Remove CSS";
+const APPLICABLE_PROTOCOLS = ["http:", "https:"];
+</pre>
+
+<p>When first loaded, the extension uses {{WebExtAPIRef("tabs.query")}} to get a list of all the tabs in the current browser window. It then loops through the tabs calling <code>initializePageAction()</code>.</p>
+
+<pre class="brush: js">var gettingAllTabs = browser.tabs.query({});
+
+gettingAllTabs.then((tabs) =&gt; {
+ for (let tab of tabs) {
+   initializePageAction(tab);
+ }
+});
+</pre>
+
+<p><code>initializePageAction</code> uses <code>protocolIsApplicable()</code> to determine whether the active tab’s URL is one the CSS can be applied to:</p>
+
+<pre class="brush: js">function protocolIsApplicable(url) {
+ var anchor =  document.createElement('a');
+ anchor.href = url;
+ return APPLICABLE_PROTOCOLS.includes(anchor.protocol);
+}
+</pre>
+
+<p>Then, if the example can act on the tab, <code>initializePageAction()</code> sets the tab’s <code>pageAction</code> (navigation bar) icon and title to use the “off” versions before making the <code>pageAction</code> visible:</p>
+
+<pre class="brush: js">function initializePageAction(tab) {
+
+ if (protocolIsApplicable(tab.url)) {
+   browser.pageAction.setIcon({tabId: tab.id, path: "icons/off.svg"});
+   browser.pageAction.setTitle({tabId: tab.id, title: TITLE_APPLY});
+   browser.pageAction.show(tab.id);
+ }
+}
+</pre>
+
+<p>Next, a listener on <code>pageAction.onClicked</code> waits for the <code>pageAction</code> icon to be clicked, and calls <code>toggleCSS</code> when it is.</p>
+
+<pre class="brush: js">browser.pageAction.onClicked.addListener(toggleCSS);</pre>
+
+<p><code>toggleCSS()</code> gets the title of the <code>pageAction</code> and then takes the action described:</p>
+
+<ul>
+ <li><strong>For "Apply CSS”:</strong>
+
+ <ul>
+ <li>toggles the <code>pageAction</code> icon and title to the “remove” versions.</li>
+ <li>applies the CSS using {{WebExtAPIRef("tabs.insertCSS")}}.</li>
+ </ul>
+ </li>
+ <li><strong>For “Remove CSS”:</strong>
+ <ul>
+ <li>toggles the <code>pageAction</code> icon and title to the “apply” versions.</li>
+ <li>removes the CSS using {{WebExtAPIRef("tabs.removeCSS")}}.</li>
+ </ul>
+ </li>
+</ul>
+
+<pre class="brush: js">function toggleCSS(tab) {
+
+
+ function gotTitle(title) {
+
+    if (title === TITLE_APPLY) {
+     browser.pageAction.setIcon({tabId: tab.id, path: "icons/on.svg"});
+     browser.pageAction.setTitle({tabId: tab.id, title: TITLE_REMOVE});
+     browser.tabs.insertCSS({code: CSS});
+    } else {
+     browser.pageAction.setIcon({tabId: tab.id, path: "icons/off.svg"});
+     browser.pageAction.setTitle({tabId: tab.id, title: TITLE_APPLY});
+     browser.tabs.removeCSS({code: CSS});
+    }
+ }
+
+ var gettingTitle = browser.pageAction.getTitle({tabId: tab.id});
+
+ gettingTitle.then(gotTitle);
+}
+</pre>
+
+<p>Finally, to ensure that the <code>pageAction</code> is valid after each update to the tab, a listener on {{WebExtAPIRef("tabs.onUpdated")}} calls <code>initializePageAction()</code> each time the tab is updated to check that the tab is still using a protocol to which the CSS can be applied.</p>
+
+<pre class="brush: js">browser.tabs.onUpdated.addListener((id, changeInfo, tab) =&gt; {
+ initializePageAction(tab);
+});
+</pre>
+
+<h2 id="Some_other_interesting_abilities">Some other interesting abilities</h2>
+
+<p>There are a couple of other Tabs API features that don’t fit into one of the earlier sections:</p>
+
+<ul>
+ <li>Capture the visible tab content with {{WebExtAPIRef("tabs.captureVisibleTab")}}.</li>
+ <li>Detect the primary language of the content in a tab using {{WebExtAPIRef("tabs.detectLanguage")}}. This could be used, for example, to match the language in your extension’s UI with that of the page it’s running in.</li>
+</ul>
+
+<h2 id="Learn_more">Learn more</h2>
+
+<p>If you want to learn more about the Tabs API, check out:</p>
+
+<ul>
+ <li><a href="/en-US/Add-ons/WebExtensions/API/tabs">Tabs API reference</a></li>
+ <li><a href="/en-US/Add-ons/WebExtensions/Examples">Example extensions</a> (many of which use the Tabs API)</li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/your_first_webextension/index.html b/files/zh-cn/mozilla/add-ons/webextensions/your_first_webextension/index.html
new file mode 100644
index 0000000000..b08f114ba1
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/your_first_webextension/index.html
@@ -0,0 +1,238 @@
+---
+title: 你的第一个拓展
+slug: Mozilla/Add-ons/WebExtensions/Your_first_WebExtension
+tags:
+ - WebExtentions
+ - 指南
+translation_of: Mozilla/Add-ons/WebExtensions/Your_first_WebExtension
+---
+<div>{{AddonSidebar}}</div>
+
+<p>在这篇文章中,我们将为 Firefox 创建一个扩展。这个扩展只是给从 "firefox.org" 或其任意子域名加载的任何页面添加一个红色边框。</p>
+
+<p>该示例的源代码位于 GitHub:<a href="https://github.com/mdn/webextensions-examples/tree/master/borderify">https://github.com/mdn/webextensions-examples/tree/master/borderify</a></p>
+
+<p>首先,你需要 Firefox 45 或更高版本。</p>
+
+<h2 id="编写扩展">编写扩展</h2>
+
+<p>创建一个新的目录并切换到该目录。例如,在你的命令行/终端,你可以这么做:</p>
+
+<pre class="brush: bash">mkdir borderify
+cd borderify</pre>
+
+<h3 id="manifest.json">manifest.json</h3>
+
+<p>现在,在 "borderify" 目录内直接创建文件 "manifest.json"。文件内容如下:</p>
+
+<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="punctuation token">{</span>
+
+ <span class="key token">"manifest_version":</span> <span class="number token">2</span><span class="punctuation token">,</span>
+ <span class="key token">"name":</span> <span class="string token">"Borderify"</span><span class="punctuation token">,</span>
+ <span class="key token">"version":</span> <span class="string token">"1.0"</span><span class="punctuation token">,</span>
+
+ <span class="key token">"description":</span> <span class="string token">"Adds a red border to all webpages matching mozilla.org."</span><span class="punctuation token">,</span>
+
+ <span class="key token">"icons":</span> <span class="punctuation token">{</span>
+ <span class="key token">"48":</span> <span class="string token">"icons/border-48.png"</span>
+ <span class="punctuation token">}</span><span class="punctuation token">,</span>
+
+ <span class="key token">"content_scripts":</span> <span class="punctuation token">[</span>
+ <span class="punctuation token">{</span>
+ <span class="key token">"matches":</span> <span class="punctuation token">[</span><span class="string token">"*://*.mozilla.org/*"</span><span class="punctuation token">]</span><span class="punctuation token">,</span>
+ <span class="key token">"js":</span> <span class="punctuation token">[</span><span class="string token">"borderify.js"</span><span class="punctuation token">]</span>
+ <span class="punctuation token">}</span>
+ <span class="punctuation token">]</span>
+
+<span class="punctuation token">}</span></code></pre>
+
+<ul>
+ <li>前三个键:<code><a href="/zh-CN/Add-ons/WebExtensions/manifest.json/manifest_version">manifest_version</a></code>、<code><a href="/zh-CN/Add-ons/WebExtensions/manifest.json/name">name</a></code> 和 <code><a href="/zh-CN/Add-ons/WebExtensions/manifest.json/version">version</a></code> 是强制的,包含有扩展的基本元数据.</li>
+ <li><code><a href="/zh-CN/Add-ons/WebExtensions/manifest.json/description">description</a></code> 是可选的,但建议使用「该描述将显示在附加组件管理器上」.</li>
+ <li><code><a href="/zh-CN/Add-ons/WebExtensions/manifest.json/icons">icons</a></code> 是可选的,但建议使用「它允许你给扩展指定一个图标,将显示在附加组件管理器上」.</li>
+</ul>
+
+<p>这里最有意思的键是 <code><a href="/zh-CN/Add-ons/WebExtensions/manifest.json/content_scripts">content_scripts</a></code>,它告诉 Firefox 加载脚本到其 URL 匹配特定模式的网页。本例中,我们要求 Firefox 加载脚本 "borderify.js" 到任何来自 "mozilla.org" 或其子域的 HTTP 或 HTTPS 页面。</p>
+
+<ul>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Content_scripts">进一步了解内容脚本 content script</a></li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Match_patterns">进一步了解模式匹配 pattern matching</a></li>
+</ul>
+
+<div class="warning">
+<p><a href="/zh-CN/Add-ons/WebExtensions/WebExtensions_and_the_Add-on_ID#When_do_you_need_an_Add-on_ID">某些情况下,你需要给你的扩展指定一个 ID</a>。如果你需要指定一个附加组件 ID,请在 <code>manifest.json</code> 中添加 <code><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings">browser_specific_settings</a></code> 键,并设置其 <code>gecko.id</code> 属性:</p>
+
+<pre class="brush: json">"browser_specific_settings": {
+ "gecko": {
+ "id": "borderify@example.com"
+ }
+}</pre>
+</div>
+
+<h3 id="iconsborder-48.png">icons/border-48.png</h3>
+
+<p>扩展应该有一个图标。这将显示在附加组件管理器加载项的列表中。我们的 manifest.json 保证了会有一个图标 "icons/border-48.png"。</p>
+
+<p>在 "borderify" 目录下直接创建 "icons" 目录,并在 "icons" 目录下保存一个名为 "border-48.png"的图标. 你可以使用<a href="https://github.com/mdn/webextensions-examples/blob/master/borderify/icons/border-48.png">我们的示例</a>中的,来自谷歌材料设计中的图标,遵循 <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-ShareAlike</a> 协议。</p>
+
+<p>如果您选择使用自己的图标,它也应该是 48×48 像素。你也可以为高分辨率显示器提供一个 96x96 的像素图标,在 manifest.json 的 <code>icons</code> 对象中添加 <code>96</code> 属性即可:</p>
+
+<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="key token">"icons":</span> <span class="punctuation token">{</span>
+ <span class="key token">"48":</span> <span class="string token">"icons/border-48.png",
+ "96": "icons/border-96.png"</span>
+<span class="punctuation token">}</span></code></pre>
+
+<p>或者,也可以在这里提供一个 SVG 文件,它会被正确地缩放。(不过:如果你正在使用 SVG 并且你的图标包含文字,有可能想要用你的 SVG 编辑器的“转换为路径”工具来拼和文字,这样图标会以一个恒定的大小/位置来缩放。)</p>
+
+<ul>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/manifest.json/icons">了解更多关于指定图标的内容</a></li>
+</ul>
+
+<h3 id="borderify.js">borderify.js</h3>
+
+<p>最后,在 "borderify" 目录下直接创建 "borderify.js" 文件,并写入下面的内容:</p>
+
+<pre class="brush: js">document.body.style.border = "5px solid red";</pre>
+
+<p>manifest.json 文件中 <code>content_scripts</code> 的键给出了一条模式匹配,该脚本便会被加载到匹配的页面中。该脚本会像页面加载自己的脚本一样被加载,可以直接访问该文档。</p>
+
+<ul>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Content_scripts">了解更多关于内容脚本的内容。</a></li>
+</ul>
+
+<h2 id="测试一下">测试一下</h2>
+
+<p>首先,仔细检查文件是否在正确的位置:</p>
+
+<pre>borderify/
+ icons/
+ border-48.png
+ borderify.js
+ manifest.json</pre>
+
+<h3 id="安装">安装</h3>
+
+<p>打开 Firefox 的 <a href="/zh-CN/docs/Tools/about:debugging">about:debugging</a> 页面,点击”This Firefox" (在新版本的Firefox里),点击 "临时加载附加组件(Load Temporary Add-on)" 按钮,并选择你的附加组件目录:</p>
+
+<p>{{EmbedYouTube("cer9EUKegG4")}}</p>
+
+<p>附加组件将会被安装,直到下次重启浏览器失效。</p>
+
+<p>或者,你可以通过 <a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Getting_started_with_web-ext">web-ext</a> 工具从命令行来运行扩展。</p>
+
+<h3 id="测试">测试</h3>
+
+<p>现在尝试访问"mozilla.org", 你将会在页面上看到有个红色的边框</p>
+
+<p>{{EmbedYouTube("rxBQl2Z9IBQ")}}</p>
+
+<div class="note">
+<p>不要在 addons.mozilla.org 上尝试!内容脚本(Content Script) 当前在那个域名下是被限制的。</p>
+</div>
+
+<p>尝试一下编辑内容脚本更改边框的颜色,或做页面内容别的修改,保存内容脚本,然后通过单击 <strong>about:debugging</strong> 页面下的 “刷新” 按钮重新加载附加的文件。你可以马上看到的变化:</p>
+
+<p>{{EmbedYouTube("NuajE60jfGY")}}</p>
+
+<ul>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">学习更多关于加载附加组件</a></li>
+</ul>
+
+<h2 id="打包和发布">打包和发布</h2>
+
+<p>为了给其他人使用你的插件,您需要打包,并将其提交给 Mozilla 进行签名。要了解更多有关,请参考 <a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Publishing_your_WebExtension">"发布你的扩展"</a>。</p>
+
+<h2 id="下一步">下一步</h2>
+
+<p>现在,你已经在开发 Firefox 的一个 Web 扩展的过程中得到了一些想法,尝试:</p>
+
+<ul>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Your_second_WebExtension">写一个更加复杂的WebExtension</a></li>
+ <li><a href="/zh-CN/Add-ons/WebExtensions/Anatomy_of_a_WebExtension">阅读更多关于WebExtensions的剖析</a></li>
+ <li><a href="https://wiki.developer.mozilla.org/zh-CN/docs/Mozilla/Add-ons/WebExtensions/Examples">探索更多关于扩展的示例</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/What_next_">发现开发,测试,和发布扩展需要的东西</a></li>
+ <li><a href="/zh-CN/docs/Mozilla/Add-ons/WebExtensions/What_next_#Continue_your_learning_experience">进一步的学习</a></li>
+</ul>
+
+<div id="SL_balloon_obj" style="display: block;">
+<div class="SL_ImTranslatorLogo" id="SL_button" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%; display: none; opacity: 1; left: 556px; top: 6804px;"></div>
+
+<div id="SL_shadow_translation_result2" style="display: none;"></div>
+
+<div id="SL_shadow_translator" style="display: none;">
+<div id="SL_planshet">
+<div id="SL_arrow_up" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;"></div>
+
+<div id="SL_Bproviders">
+<div class="SL_BL_LABLE_ON" id="SL_P0" title="Google">G</div>
+
+<div class="SL_BL_LABLE_ON" id="SL_P1" title="Microsoft">M</div>
+
+<div class="SL_BL_LABLE_ON" id="SL_P2" title="Translator">T</div>
+</div>
+
+<div id="SL_alert_bbl" style="display: none;">
+<div id="SLHKclose" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;"></div>
+
+<div id="SL_alert_cont"></div>
+</div>
+
+<div id="SL_TB">
+<table id="SL_tables">
+ <tbody>
+ <tr>
+ <td class="SL_td"><input></td>
+ <td class="SL_td"><select><option value="auto">检测语言</option><option value="eo">世界语</option><option value="zh-CN">中文简体</option><option value="zh-TW">中文繁体</option><option value="da">丹麦语</option><option value="uk">乌克兰语</option><option value="uz">乌兹别克语</option><option value="ur">乌尔都语</option><option value="hy">亚美尼亚语</option><option value="ig">伊博语</option><option value="ru">俄语</option><option value="bg">保加利亚语</option><option value="si">僧伽罗语</option><option value="hr">克罗地亚语</option><option value="is">冰岛语</option><option value="gl">加利西亚语</option><option value="ca">加泰罗尼亚语</option><option value="hu">匈牙利语</option><option value="zu">南非祖鲁语</option><option value="kn">卡纳达语</option><option value="hi">印地语</option><option value="su">印尼巽他语</option><option value="jw">印尼爪哇语</option><option value="id">印尼语</option><option value="gu">古吉拉特语</option><option value="kk">哈萨克语</option><option value="tr">土耳其语</option><option value="tg">塔吉克语</option><option value="sr">塞尔维亚语</option><option value="st">塞索托语</option><option value="cy">威尔士语</option><option value="bn">孟加拉语</option><option value="ceb">宿务语</option><option value="ne">尼泊尔语</option><option value="eu">巴斯克语</option><option value="af">布尔语(南非荷兰语)</option><option value="iw">希伯来语</option><option value="el">希腊语</option><option value="de">德语</option><option value="it">意大利语</option><option value="yi">意第绪语</option><option value="la">拉丁语</option><option value="lv">拉脱维亚语</option><option value="no">挪威语</option><option value="cs">捷克语</option><option value="sk">斯洛伐克语</option><option value="sl">斯洛文尼亚语</option><option value="sw">斯瓦希里语</option><option value="pa">旁遮普语</option><option value="ja">日语</option><option value="ka">格鲁吉亚语</option><option value="mi">毛利语</option><option value="fr">法语</option><option value="pl">波兰语</option><option value="bs">波斯尼亚语</option><option value="fa">波斯语</option><option value="te">泰卢固语</option><option value="ta">泰米尔语</option><option value="th">泰语</option><option value="ht">海地克里奥尔语</option><option value="ga">爱尔兰语</option><option value="et">爱沙尼亚语</option><option value="sv">瑞典语</option><option value="be">白俄罗斯语</option><option value="lt">立陶宛语</option><option value="so">索马里语</option><option value="yo">约鲁巴语</option><option value="my">缅甸语</option><option value="ro">罗马尼亚语</option><option value="lo">老挝语</option><option value="fi">芬兰语</option><option value="hmn">苗语</option><option value="en">英语</option><option value="nl">荷兰语</option><option value="tl">菲律宾语</option><option value="pt">葡萄牙语</option><option value="mn">蒙古语</option><option value="es">西班牙语</option><option value="ha">豪萨语</option><option value="vi">越南语</option><option value="az">阿塞拜疆语</option><option value="sq">阿尔巴尼亚语</option><option value="ar">阿拉伯语</option><option value="ko">韩语</option><option value="mk">马其顿语</option><option value="mg">马尔加什语</option><option value="mr">马拉地语</option><option value="ml">马拉雅拉姆语</option><option value="ms">马来语</option><option value="mt">马耳他语</option><option value="km">高棉语</option><option value="ny">齐切瓦语</option></select></td>
+ <td class="SL_td">
+ <div id="SL_switch_b" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="切换语言"></div>
+ </td>
+ <td class="SL_td"><select><option value="eo">世界语</option><option selected value="zh-CN">中文简体</option><option value="zh-TW">中文繁体</option><option value="da">丹麦语</option><option value="uk">乌克兰语</option><option value="uz">乌兹别克语</option><option value="ur">乌尔都语</option><option value="hy">亚美尼亚语</option><option value="ig">伊博语</option><option value="ru">俄语</option><option value="bg">保加利亚语</option><option value="si">僧伽罗语</option><option value="hr">克罗地亚语</option><option value="is">冰岛语</option><option value="gl">加利西亚语</option><option value="ca">加泰罗尼亚语</option><option value="hu">匈牙利语</option><option value="zu">南非祖鲁语</option><option value="kn">卡纳达语</option><option value="hi">印地语</option><option value="su">印尼巽他语</option><option value="jw">印尼爪哇语</option><option value="id">印尼语</option><option value="gu">古吉拉特语</option><option value="kk">哈萨克语</option><option value="tr">土耳其语</option><option value="tg">塔吉克语</option><option value="sr">塞尔维亚语</option><option value="st">塞索托语</option><option value="cy">威尔士语</option><option value="bn">孟加拉语</option><option value="ceb">宿务语</option><option value="ne">尼泊尔语</option><option value="eu">巴斯克语</option><option value="af">布尔语(南非荷兰语)</option><option value="iw">希伯来语</option><option value="el">希腊语</option><option value="de">德语</option><option value="it">意大利语</option><option value="yi">意第绪语</option><option value="la">拉丁语</option><option value="lv">拉脱维亚语</option><option value="no">挪威语</option><option value="cs">捷克语</option><option value="sk">斯洛伐克语</option><option value="sl">斯洛文尼亚语</option><option value="sw">斯瓦希里语</option><option value="pa">旁遮普语</option><option value="ja">日语</option><option value="ka">格鲁吉亚语</option><option value="mi">毛利语</option><option value="fr">法语</option><option value="pl">波兰语</option><option value="bs">波斯尼亚语</option><option value="fa">波斯语</option><option value="te">泰卢固语</option><option value="ta">泰米尔语</option><option value="th">泰语</option><option value="ht">海地克里奥尔语</option><option value="ga">爱尔兰语</option><option value="et">爱沙尼亚语</option><option value="sv">瑞典语</option><option value="be">白俄罗斯语</option><option value="lt">立陶宛语</option><option value="so">索马里语</option><option value="yo">约鲁巴语</option><option value="my">缅甸语</option><option value="ro">罗马尼亚语</option><option value="lo">老挝语</option><option value="fi">芬兰语</option><option value="hmn">苗语</option><option value="en">英语</option><option value="nl">荷兰语</option><option value="tl">菲律宾语</option><option value="pt">葡萄牙语</option><option value="mn">蒙古语</option><option value="es">西班牙语</option><option value="ha">豪萨语</option><option value="vi">越南语</option><option value="az">阿塞拜疆语</option><option value="sq">阿尔巴尼亚语</option><option value="ar">阿拉伯语</option><option value="ko">韩语</option><option value="mk">马其顿语</option><option value="mg">马尔加什语</option><option value="mr">马拉地语</option><option value="ml">马拉雅拉姆语</option><option value="ms">马来语</option><option value="mt">马耳他语</option><option value="km">高棉语</option><option value="ny">齐切瓦语</option></select></td>
+ <td class="SL_td">
+ <div id="SL_TTS_voice" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="聆听翻译"></div>
+ </td>
+ <td class="SL_td">
+ <div class="SL_copy" id="SL_copy" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="复制译文"></div>
+ </td>
+ <td class="SL_td">
+ <div id="SL_bbl_font_patch"></div>
+
+ <div class="SL_bbl_font" id="SL_bbl_font" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="字体大小"></div>
+ </td>
+ <td class="SL_td">
+ <div id="SL_bbl_help" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="帮助"></div>
+ </td>
+ <td class="SL_td">
+ <div class="SL_pin_off" id="SL_pin" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="固定弹出窗口"></div>
+ </td>
+ </tr>
+ </tbody>
+</table>
+</div>
+</div>
+
+<div id="SL_shadow_translation_result"></div>
+
+<div class="SL_loading" id="SL_loading" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;"></div>
+
+<div id="SL_player2"></div>
+
+<div id="SL_alert100">文本转语音功能仅限200个字符</div>
+
+<div id="SL_Balloon_options" style="background: rgb(255, 255, 255) repeat scroll 0% 0%;">
+<div id="SL_arrow_down" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;"></div>
+
+<table id="SL_tbl_opt" style="width: 100%;">
+ <tbody>
+ <tr>
+ <td><input></td>
+ <td>
+ <div id="SL_BBL_IMG" style="background: rgba(0, 0, 0, 0) repeat scroll 0% 0%;" title="显示翻译器的按钮 3 秒"></div>
+ </td>
+ <td><a class="SL_options" title="显示选项">选项</a> : <a class="SL_options" title="翻译历史记录">历史</a> : <a class="SL_options" title="反馈">反馈</a> : <a class="SL_options" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=GD9D8CPW8HFA2" title="作出一点点贡献">Donate</a></td>
+ <td><span id="SL_Balloon_Close" title="关闭">关闭</span></td>
+ </tr>
+ </tbody>
+</table>
+</div>
+</div>
+</div>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/实现一个设置页面/index.html b/files/zh-cn/mozilla/add-ons/webextensions/实现一个设置页面/index.html
new file mode 100644
index 0000000000..fe8ac2e0a7
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/实现一个设置页面/index.html
@@ -0,0 +1,203 @@
+---
+title: 实现一个设置页面
+slug: Mozilla/Add-ons/WebExtensions/实现一个设置页面
+translation_of: Mozilla/Add-ons/WebExtensions/Implement_a_settings_page
+---
+<div>{{AddonSidebar}}</div>
+
+<p>设置页面可以让用户查看,修改扩展的一些设置。</p>
+
+<p>对于WebExtensions,设置通常使用 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage">storage</a></code> API 保存. 实现一个设置页面通常包含以下三步:</p>
+
+<ul>
+ <li>制作一个HTML 文件用以显示并修改设置</li>
+ <li>写一个包含于该HTML文件的脚本,其可以使设置页面存储与存储设备中并在用户修改后更新他。</li>
+ <li>在manifest.json文件 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/options_ui">options_ui</a></code> 关键字中 设置HTML文件的路径。通过这种方式,该HTML将会被显示浏览器管理器里该插件名字和描述的旁边。</li>
+</ul>
+
+<div class="note">
+<p>你也可以使用 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/openOptionsPage">runtime.openOptionsPage()</a></code> 打开该页面。</p>
+</div>
+
+<h2 id="简单的_WebExtension">简单的 WebExtension</h2>
+
+<p>首先,我们写一个向用户访问的所有页面添加一个蓝色边框的扩展。</p>
+
+<p>创建一个新的文件夹命名为“setting”,然后创建文件“manifest.json”它包含以下内容:</p>
+
+<pre class="brush: json">{
+
+ "manifest_version": 2,
+ "name": "Settings example",
+ "version": "1.0",
+
+ "content_scripts": [
+ {
+ "matches": ["&lt;all_urls&gt;"],
+ "js": ["borderify.js"]
+ }
+ ]
+
+}</pre>
+
+<p>该扩展指示浏览器在用户访问的网站上加载一个名为"borderify.js“的Content Script。</p>
+
+<p>接下来,在"setting"目录下创建"borderify.js",然后给予他以下内容:</p>
+
+<pre class="brush: js">document.body.style.border = "10px solid blue";</pre>
+
+<p>这只是向网页加入了一一个蓝色边框</p>
+
+<p>现在 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox">安装该扩展</a> 并测试它——打开任意一个网页:</p>
+
+<p>{{EmbedYouTube("E-WUhihF8fw")}}</p>
+
+<h2 id="添加设置页面">添加设置页面</h2>
+
+<p>现在让我们创建一个设置页面来允许用户设置边框的颜色。</p>
+
+<p>首先更新 "manifest.json" 使他拥有如下内容:</p>
+
+<pre class="brush: json">{
+
+ "manifest_version": 2,
+ "name": "Settings example",
+ "version": "1.0",
+
+ "content_scripts": [
+ {
+ "matches": ["&lt;all_urls&gt;"],
+ "js": ["borderify.js"]
+ }
+ ],
+
+ "options_ui": {
+ "page": "options.html"
+ },
+
+ "permissions": ["storage"]
+
+}
+</pre>
+
+<p>我们加入了两个manifest 关键字:</p>
+
+<ul>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/options_ui">options_ui</a></code>: 设置了一个HTML来作为设置页面。</li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a></code>: 我们使用 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage">storage</a></code> API 来保存设置, 所以我们需要请求权限来使用该API。</li>
+</ul>
+
+<p>接下来,因为我们承诺提供"options.html",让我们来创建他,在"setting"目录创建一个该文件并具有以下内容:</p>
+
+<pre class="brush: html">&lt;!DOCTYPE html&gt;
+
+&lt;html&gt;
+ &lt;head&gt;
+ &lt;meta charset="utf-8"&gt;
+ &lt;/head&gt;
+
+ &lt;body&gt;
+
+ &lt;form&gt;
+ &lt;label&gt;Border color&lt;input type="text" id="color" &gt;&lt;/label&gt;
+ &lt;button type="submit"&gt;Save&lt;/button&gt;
+ &lt;/form&gt;
+
+ &lt;script src="options.js"&gt;&lt;/script&gt;
+
+ &lt;/body&gt;
+
+&lt;/html&gt;
+</pre>
+
+<p>这里定义了一个带有标记文字{{htmlelement("input")}}的 {{htmlelement("form")}} 和一个 提交 {{htmlelement("button")}}. 也包含了一个名为"options.js"的脚本。</p>
+
+<p>仍然在"settting"目录下创建 "options.js",并给予他以下内容:</p>
+
+<pre class="brush: js">function saveOptions(e) {
+ e.preventDefault();
+ browser.storage.local.set({
+ color: document.querySelector("#color").value
+ });
+}
+
+function restoreOptions() {
+
+ function setCurrentChoice(result) {
+ document.querySelector("#color").value = result.color || "blue";
+ }
+
+ function onError(error) {
+ console.log(`Error: ${error}`);
+ }
+
+ var getting = browser.storage.local.get("color");
+ getting.then(setCurrentChoice, onError);
+}
+
+document.addEventListener("DOMContentLoaded", restoreOptions);
+document.querySelector("form").addEventListener("submit", saveOptions);
+</pre>
+
+<p>它做了两件事:</p>
+
+<ul>
+ <li>当网页被加载它使用<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea/get">storage.local.get()</a></code> 从存贮设备中获取了名为"color”的值.如果该值未被设置其为默认值blue。</li>
+ <li>当用户点击提交按钮,使用<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea/set">storage.local.set()</a></code> 存贮颜色值。</li>
+</ul>
+
+<p>最后,更新"borderify.js" 来读取边框颜色:</p>
+
+<div class="warning">
+<p>因为 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage/StorageArea/get">browser.storage.local.get()</a> 在火狐52版本之前的一个漏洞 ,以下代码没法起作用。为了使它生效,<code>onGot()中的 item.color 必须改为 item[0].color。</code></p>
+</div>
+
+<pre class="brush: js"> function onError(error) {
+ console.log(`Error: ${error}`);
+}
+
+function onGot(item) {
+ var color = "blue";
+ if (item.color) {
+ color = item.color;
+ }
+ document.body.style.border = "10px solid " + color;
+}
+
+var getting = browser.storage.local.get("color");
+getting.then(onGot, onError);
+</pre>
+
+<p>最后,完整的扩展看起来是这样:</p>
+
+<pre>settings/
+ borderify.js
+ manifest.json
+ options.html
+ options.js</pre>
+
+<p>现在:</p>
+
+<ul>
+ <li><a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Temporary_Installation_in_Firefox#Reloading_a_temporary_add-on">重新载入扩展</a></li>
+ <li>加载一个网页</li>
+ <li>打开设置页面并修改边框颜色</li>
+ <li>重载网页查看变化。</li>
+</ul>
+
+<p>在火狐中你可以通过访问"about:addons"点击扩展旁边的"Preferences"按钮访问设置页面。</p>
+
+<p>{{EmbedYouTube("ECt9cbWh1qs")}}</p>
+
+<h2 id="进一步了解">进一步了解</h2>
+
+<ul>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/options_ui">options_ui</a></code> 关键字文档</li>
+ <li><code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage">storage</a></code> API 文档</li>
+ <li>使用<code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/openOptionsPage">runtime.openOptionsPage()</a></code> 直接打开你的设置页面</li>
+ <li>另一个设置页面例子:
+ <ul>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/favourite-colour">favourite-colour</a></li>
+ </ul>
+ </li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/构建一个跨浏览器的扩展插件/index.html b/files/zh-cn/mozilla/add-ons/webextensions/构建一个跨浏览器的扩展插件/index.html
new file mode 100644
index 0000000000..6d1a21497c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/构建一个跨浏览器的扩展插件/index.html
@@ -0,0 +1,275 @@
+---
+title: 构建一个跨浏览器的扩展程序
+slug: Mozilla/Add-ons/WebExtensions/构建一个跨浏览器的扩展插件
+tags:
+ - Web插件
+ - 扩展
+ - 指南
+ - 插件
+translation_of: Mozilla/Add-ons/WebExtensions/Build_a_cross_browser_extension
+---
+<p>{{AddonSidebar()}}</p>
+
+<p>浏览器扩展 API 的引入为浏览器扩展的开发创造了 “一次开发跨浏览器” 的前景。然而,在使用扩展 API 的浏览器中(主要是 Chrome、 Firefox、 Opera 和 Edge) ,API 的实现和覆盖范围都存在差异。除此之外,Safari 使用了它自己的 Safari 扩展脚本系统。</p>
+
+<p>最大化兼容浏览器扩展意味着至少在两个不同的浏览器上兼容同一个扩展。本文探讨了在创建跨浏览器扩展时所面临的六个主要挑战,并在每种情况下提出了如何应对这些挑战。</p>
+
+<p>本文不讨论为 Safari 构建浏览器扩展。您可以通过 Safari 扩展共享一些资源,比如图片和 HTML 内容。然而,如果您要进行 JavaScript 部分的编程则需要作为一个单独的开发项目进行,除非您希望创建自己的 polyfill。</p>
+
+<h2 id="跨平台扩展的开发障碍">跨平台扩展的开发障碍</h2>
+
+<p>在开发跨平台扩展时,需要注意以下六个方面:</p>
+
+<ul>
+ <li>API 命名空间</li>
+ <li>API 异步事件处理</li>
+ <li>API 函数覆盖率</li>
+ <li>Manifest 的字段</li>
+ <li>打包扩展</li>
+ <li>发布扩展</li>
+</ul>
+
+<h3 id="API_命名空间">API 命名空间</h3>
+
+<p>在四大主流浏览器中,有两个 API 命名空间正在使用:</p>
+
+<ul>
+ <li><code>browser.* </code>是 Firefox 和 Edge 使用的扩展 API 的标准</li>
+ <li><code>chrome.*</code> 是 Chrome 和 Opera 使用的扩展 API 的标准</li>
+</ul>
+
+<p>Firefox 也支持 Chrome 浏览器的 <code>chrome.*</code> 名称空间,主要用于协助扩展移植。然而,首选应该使用浏览器 <code>browser.*</code> 命名空间。除了被提议的标准外, <code>browser.*</code> 使用 promises ーー一种现代化且简单的处理异步事件机制。</p>
+
+<p>只有在非常小的扩展中,命名空间才可能是唯一的跨平台问题。因此,如果你遇到了且试图专门解决这个问题的话,可能很少会有帮助。最好的方法是通过异步事件处理来解决这个问题。</p>
+
+<h3 id="API_异步事件处理">API 异步事件处理</h3>
+
+<p>在四个主要浏览器中,有两种方法可以处理异步事件:</p>
+
+<ul>
+ <li>promises 是 Firefox 使用的扩展 API 的标准</li>
+ <li>callbacks 是 Chrome、Edge 和 Opera 使用的扩展 API 的标准</li>
+</ul>
+
+<p>Firefox 还支持 <code>chrome.*</code> 命名空间中的 callbacks 风格的 API,这主要是为了便于从 Chrome <a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Porting_a_Google_Chrome_extension">迁移</a>。然而,应该首选使用 promises(以及 <code>browser.*</code> 命名空间),它已被采纳为拟议标准的一部分。它极大地简化了异步事件处理,特别是在需要将事件链接在一起的情况下。</p>
+
+<div class="blockIndicator note">
+<p>如果你对这两种方法之间的差异不熟悉,可以看一下 <a href="https://medium.com/codebuddies/getting-to-know-asynchronous-javascript-callbacks-promises-and-async-await-17e0673281ee">了解异步 JavaScript: Callbacks、 Promises 和 Async/Await </a>或者 MDN 的 <a href="/en-US/docs/Web/JavaScript/Guide/Using_promises">Using promises</a> 页面。</p>
+</div>
+
+<h4 id="浏览器扩展_API_的垫片(Polyfill)">浏览器扩展 API 的垫片(Polyfill)</h4>
+
+<p>那么,当 Firefox 是唯一支持它的浏览器时,你如何轻松地使用 promises 呢?解决方案是使用 promises 为 Firefox 编程,并使用<a href="https://github.com/mozilla/webextension-polyfill/">浏览器扩展 API 的垫片(Polyfill)</a>!<br>
+ <br>
+ 这个 polyfill 解决了跨 Firefox、 Chrome 和 Opera 的 API 名称空间和异步事件处理。在撰写本报告时(2018年11月) ,Edge 的支持正在开发中。<br>
+ <br>
+ 要使用 polyfill,可以使用 npm 安装到开发环境中,或者直接从 <a href="https://github.com/mozilla/webextension-polyfill/releases">GitHub Relase</a> 页面下载。</p>
+
+<p>然后,引入 <code>browser-polyfill.js</code> 到:</p>
+
+<ul>
+ <li><code>manifest.json</code>,修改后使它可以用于 background 和 content 脚本</li>
+ <li>HTML 文件,例如 <code>browserAction</code> 弹出窗口或标签页</li>
+ <li>使用 <code>tabs.executeScript</code> 上的 <code>executeScript</code> 动态注入脚本(不需要事先在 manifest.json 的 <code>content_scripts</code> 中申明</li>
+</ul>
+
+<p>例如,这个 <code>manifest.json</code> 代码让你的后台脚本可以使用 polyfill:</p>
+
+<pre class="brush: json notranslate">{
+ // ...
+ "background": {
+ "scripts": [
+ "browser-polyfill.js",
+ "background.js"
+ ]
+ }
+}</pre>
+
+<p>您的目标是确保在任何其他扩展脚本执行 <code>browser.*</code> API 前执行 polyfill。</p>
+
+<div class="blockIndicator note">
+<p>关于如何使用模块打包器使用 polyfill 的更多细节和信息,请参阅 <a href="https://github.com/mozilla/webextension-polyfill/blob/master/README.md">GitHub 上的项目自述文件</a>。</p>
+</div>
+
+<p>还有其他的 polyfill 选项,但是在撰写本文时,没有一个提供浏览器扩展 API polyfill 的覆盖范围。所以,如果你没有把 Firefox 作为你的首选,你的选择就是接受 polyfills 的限制,移植到 Firefox 并添加跨浏览器的支持,或者开发你自己的 polyfill。</p>
+
+<h3 id="API_函数覆盖率">API 函数覆盖率</h3>
+
+<p>这四个主要浏览器提供的 API 函数的实现差异可分为三大类:</p>
+
+<ul>
+ <li><strong>缺乏对整个功能的支持。</strong>例如,在撰写本文时,Edge 没有提供对<a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/privacy#Browser_compatibility">隐私</a>功能的支持。</li>
+ <li><strong>缺乏对某些特性的支持。</strong>例如,在撰写本文时,Firefox 不支持 <code>onButtonClicked</code>,而只支持 <code>onShown</code>。</li>
+ <li><strong>专有功能,支持特定于浏览器的特性。</strong>例如,在撰写本文时,容器是一个特定于 firefox 的特性,由 <code>contextualidentity</code> 函数支持。</li>
+</ul>
+
+<p>你可以在 <a href="https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_support_for_JavaScript_APIs">Mozilla Developer Network 浏览器对 JavaScript API 页面的支持</a>上找到4个主要浏览器对扩展 API 的支持细节,以及 Firefox for Android 对扩展 API 的支持细节。浏览器兼容性信息也包含在每个函数及其方法、类型和事件的 Mozilla Developer Network <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/API">JavaScript APIs</a> 参考页面中。</p>
+
+<h4 id="处理_API_差异">处理 API 差异</h4>
+
+<p>解决这些差异的一个简单方法是将扩展中使用的函数限制在没有 API 差异的函数范围内。在实践中,对于大多数扩展,这种方法可能限制性太强。<br>
+ <br>
+ 相反,如果 API 之间存在差异,则应该提供替代实现或降级功能。(请记住: 您可能还需要这样考虑同一浏览器的不同版本之间的 API 支持差异。)</p>
+
+<p>使用运行时检查函数特性的可用性是实现备选或降级功能的推荐方法。执行运行时检查的好处是,如果函数是可用的,您不需要更新和重新分发扩展来使用它。</p>
+
+<p>下面的代码使您能够执行运行时检查:</p>
+
+<pre class="brush: js notranslate">if (typeof &lt;function&gt; === "function") {
+ // safe to use the function
+}</pre>
+
+<h3 id="Manifest_字段">Manifest 字段</h3>
+
+<p>4个主要浏览器支持的 <code><a href="/zh-CN/docs/https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Browser_compatibility_for_manifest.json">manifest.json</a></code> 文件字段的差异大致可分为三类:</p>
+
+<ul>
+ <li><strong>扩展信息属性。</strong>例如,在撰写本文时,Firefox 和 Opera 包含和 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/author#Browser_compatibility">author</a></code> 地位相等的 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/developer#Browser_compatibility">developer</a></code> 关键字,以获取扩展的开发者和作者的详细信息。</li>
+ <li><strong>扩展功能。</strong>例如,在编写本文时,Edge 不支持扩展定义快捷键的 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/commands#Browser_compatibility">commands</a></code> 字段。</li>
+ <li><strong>字段可选性。</strong>例如,在编写本文时,在 Edge 中 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/author#Browser_compatibility">author</a></code> 字段是必需的,但在其他主要浏览器中是可选的。</li>
+</ul>
+
+<p>浏览器兼容性信息包含在 Mozilla Developer Network <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json">manifest.json</a></code> 页的每个字段中。</p>
+
+<p><code>manifest.json</code> 文件在不同浏览器之间的版本号可能有所不同,为每个浏览器创建和编辑一个静态版本号通常是最简单的方法。</p>
+
+<h3 id="扩展打包">扩展打包</h3>
+
+<p>通过浏览器扩展商店打包和分发扩展相对简单。</p>
+
+<ul>
+ <li><font>火狐、 Chrome 和 Opera 都使用简单的 zip 格式打包,同时需要 </font><code>manifest.json</code> <font>文件位于压缩包的根目录。</font></li>
+ <li><font>但是,提交到 Microsoft 扩展商店需要对扩展文件进行额外打包。</font></li>
+</ul>
+
+<p>有关打包的详细信息,请参阅相应扩展的开发人员门户网站上的指南。</p>
+
+<h3 id="扩展发布">扩展发布</h3>
+
+<p>这四种主要浏览器都维护有浏览器扩展商店。每个商店还对扩展进行审核,以检查安全漏洞。</p>
+
+<p>因此,您需要为每个商店分别添加和更新扩展。在某些情况下,您可以使用脚本上传扩展。</p>
+
+<p>下表总结了每个商店的做法和特点:</p>
+
+<table>
+ <tbody>
+ <tr>
+ <td></td>
+ <td>
+ <p>注册费</p>
+ </td>
+ <td>
+ <p>上传模块</p>
+ </td>
+ <td>
+ <p>发布审核</p>
+ </td>
+ <td>
+ <p>开发者账号需要2FA验证</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p>Firefox</p>
+ </td>
+ <td>
+ <p>否</p>
+ </td>
+ <td>
+ <p><a href="/en-US/Add-ons/WebExtensions/web-ext_command_reference">web-ext</a></p>
+ </td>
+ <td>
+ <p>全自动,仅需要几秒钟<sup>1</sup></p>
+ </td>
+ <td>
+ <p>否</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p>Chrome</p>
+ </td>
+ <td>
+ <p>是</p>
+ </td>
+ <td>
+ <p>是</p>
+ </td>
+ <td>
+ <p>全自动,短于一小时</p>
+ </td>
+ <td>
+ <p>是</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p>Opera</p>
+ </td>
+ <td>
+ <p>否</p>
+ </td>
+ <td>
+ <p>否</p>
+ </td>
+ <td>
+ <p>人工审核,但不需要提供SLA</p>
+ </td>
+ <td>
+ <p>否</p>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <p>Edge</p>
+ </td>
+ <td>
+ <p>是</p>
+ </td>
+ <td>
+ <p>否</p>
+ </td>
+ <td>
+ <p>人工审核,需要72小时<sup>2</sup></p>
+ </td>
+ <td>
+ <p>是</p>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p><sup>1</sup> 在发布后会延期进行一次人工审查,如果发现了需要解决的问题,可能导致扩展被暂停。</p>
+
+<p><sup>2</sup> 在撰写本文时,微软只允许发布预先批准的扩展。</p>
+
+<h3 id="其他考虑">其他考虑</h3>
+
+<h4 id="扩展命名">扩展命名</h4>
+
+<p>Microsoft 要求扩展具有唯一的名称,并通过 Windows Dev Center 为扩展声明一个或多个名称。因此,即使您不打算立即支持 Edge,为微软保留一个扩展名可能是最谨慎的做法。</p>
+
+<h4 id="版本号指定">版本号指定</h4>
+
+<p>Firefox 和 Chrome 商店要求每个上传的扩展发布包都有一个单独的版本号。这意味着如果在线上遇到问题,就不能恢复到之前的版本号。</p>
+
+<h4 id="在不同的实现中共享资源">在不同的实现中共享资源</h4>
+
+<p>即使你要支持的平台中包括 Safari,仍然可以在对于不同浏览器的实现中共享许多资源。其中包括:</p>
+
+<ul>
+ <li>Images</li>
+ <li>HTML</li>
+ <li>CSS</li>
+</ul>
+
+<h2 id="总结">总结</h2>
+
+<p>在进行跨平台扩展开发时,可以通过对标 Firefox 和使用 <a href="https://github.com/mozilla/webextension-polyfill/">WebExtension API Polyfill</a> 来解决扩展 API 之间的根本差异。遵循这种方法,您将在使用与提议的 WebExtension API 标准紧密结合的 API 特性中受益,并使用 promises 来简单的处理异步事件。</p>
+
+<p>跨平台工作的主要重点可能是处理主要浏览器支持的 API 特性之间的差异。创建你的 <code>manifest.json</code> 文件应该是相对简单的,你可以手动完成。然后,您将需要考虑扩展包中的打包差异,以及提交到每个扩展商店的过程差异。</p>
+
+<p>您同时可以使用<a href="https://github.com/notlmn/browser-extension-template"> browser-extension-template</a> 用于快速设置、生成和发布浏览器扩展项目。</p>
+
+<p>根据本文中的建议,您现在应该能够创建一个在四种主要浏览器上都运行良好的扩展程序,使您能够将扩展功能交付给更多的人。</p>
diff --git a/files/zh-cn/mozilla/add-ons/webextensions/用户界面元素/index.html b/files/zh-cn/mozilla/add-ons/webextensions/用户界面元素/index.html
new file mode 100644
index 0000000000..1e99cab52c
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/webextensions/用户界面元素/index.html
@@ -0,0 +1,162 @@
+---
+title: 用户界面元素
+slug: Mozilla/Add-ons/WebExtensions/用户界面元素
+translation_of: Mozilla/Add-ons/WebExtensions/user_interface
+---
+<div>{{AddonSidebar}}</div>
+
+<p>该主题概括了所有你能用来创建你扩展的用户界面的组件。</p>
+
+<h2 id="浏览器行为">浏览器行为</h2>
+
+<p>浏览器行为是一个你能添加至浏览器工具栏的按钮,用户可以点击该按钮来与你的扩展交互。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/12966/browser-action.png" style="display: block; height: 387px; margin-left: auto; margin-right: auto; width: 782px;"></p>
+
+<p>有两种方式定义一个浏览器行为: 有一个 <a href="#Popups">弹出菜单</a>, 或者没有弹出菜单。</p>
+
+<p>当你没有定义一个弹出菜单时,用户点击按钮会导致一个消息被分发至扩展,而你可以使用 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/BrowserAction/onClicked" title="Fired when a browser action icon is clicked. This event will not fire if the browser action has a popup."><code>browserAction.onClicked</code></a> 来监听它:</p>
+
+<pre class="brush: js line-numbers language-js"><code class="language-js">browser<span class="punctuation token">.</span>browserAction<span class="punctuation token">.</span>onClicked<span class="punctuation token">.</span><span class="function token">addListener</span><span class="punctuation token">(</span>handleClick<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>
+
+<p>如果你定义了弹出菜单,点击事件就不会被分发取而代之的是弹出菜单会显示出来。用户可以跟弹出菜单交互而当用户点击菜单外的区域时它会自动关闭。</p>
+
+<p>值得注意的是你的扩展只能拥有一个浏览器行为。</p>
+
+<h3 id="定义浏览器行为">定义浏览器行为</h3>
+
+<p>你通过使用在manifest.json 文件中使用 <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code> 关键字定义浏览器行为的属性 - 图标, 标题, 弹出菜单 :</p>
+
+<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="key token">"browser_action":</span> <span class="punctuation token">{</span>
+ <span class="key token">"default_icon":</span> <span class="punctuation token">{</span>
+ <span class="key token">"19":</span> <span class="string token">"button/geo-19.png"</span><span class="punctuation token">,</span>
+ <span class="key token">"38":</span> <span class="string token">"button/geo-38.png"</span>
+ <span class="punctuation token">}</span><span class="punctuation token">,</span>
+ <span class="key token">"default_title":</span> <span class="string token">"Whereami?"</span><span class="punctuation token">,</span>
+ <span class="key token">"default_popup":</span> <span class="string token">"popup/geo.html"</span>
+<span class="punctuation token">}</span></code></pre>
+
+<p>唯一必要的关键字是 <code>default_icon</code>.你可以使用 <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction">browserAction</a></code> API 修改任何属性.</p>
+
+<h3 id="例子">例子</h3>
+
+<p>在GITHUB上的 <a href="https://github.com/mdn/webextensions-examples">webextensions-examples</a> 资源包含了以下使用浏览行为的例子:</p>
+
+<ul>
+ <li><a href="https://github.com/mdn/webextensions-examples/blob/master/bookmark-it/">bookmark-it</a> 使用了没有弹出菜单的浏览器行为</li>
+ <li><a href="https://github.com/mdn/webextensions-examples/tree/master/beastify">beastify</a> 使用了由弹出菜单的浏览器行为</li>
+</ul>
+
+<h2 id="页面行为">页面行为</h2>
+
+<p>页面行为在很多方面类似于 <a href="#Browser_actions">browser actions</a> , 除了:</p>
+
+<ul>
+ <li>浏览器行为按钮会一直显现,并且一直可用。</li>
+ <li>页面行为只会在几个页面并且该页面处于活动标签时显示。</li>
+</ul>
+
+<p>为了强调页面行为只跟部分页面有联系,他们将其显示在地址栏内而不是工具栏:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/12960/page-action.png" style="display: block; height: 262px; margin-left: auto; margin-right: auto; width: 850px;"></p>
+
+<p>不像浏览器行为,页面行为默认是关闭的, 调用 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/PageAction/show" title="Shows the page action for a given tab. The page action is shown whenever the given tab is the active tab."><code>pageAction.show()</code></a> 和<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/PageAction/hide" title="Hides the page action for a given tab."><code>pageAction.hide()</code></a> 可以显示或隐藏页面行为。</p>
+
+<h3 id="定义页面行为">定义页面行为</h3>
+
+<p>通过在manifest.json中使用<code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/page_action">page_action</a></code> 关键字来定义页面行为的属性 —— 图标, 标题, 弹出菜单:</p>
+
+<pre class="brush: json line-numbers language-json"><code class="language-json"><span class="key token">"page_action":</span> <span class="punctuation token">{</span>
+ <span class="key token">"browser_style":</span> <span class="keyword token">true</span><span class="punctuation token">,</span>
+ <span class="key token">"default_icon":</span> <span class="punctuation token">{</span>
+ <span class="key token">"19":</span> <span class="string token">"button/geo-19.png"</span><span class="punctuation token">,</span>
+ <span class="key token">"38":</span> <span class="string token">"button/geo-38.png"</span>
+ <span class="punctuation token">}</span><span class="punctuation token">,</span>
+ <span class="key token">"default_title":</span> <span class="string token">"Whereami?"</span><span class="punctuation token">,</span>
+ <span class="key token">"default_popup":</span> <span class="string token">"popup/geo.html"</span>
+<span class="punctuation token">}</span></code></pre>
+
+<p><code>default_icon 是唯一强制要求的关键字</code>. 你可以使用 <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/browserAction">pageAction</a></code> API 修改所有的属性或现实或隐藏页面行为。</p>
+
+<h3 id="例子_2">例子</h3>
+
+<p> <a href="https://github.com/mdn/webextensions-examples/tree/master/chill-out">chill-out</a> 例子使用了一个页面行为。</p>
+
+<h2 id="弹出菜单">弹出菜单</h2>
+
+<p>一个弹出菜单是一个绑定至 <a href="#Browser_actions">browser action</a> 或者 <a href="#Page_actions">page action</a>  的对话框。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/14039/popup-shadow.png" style="display: block; height: 545px; margin-left: auto; margin-right: auto; width: 700px;"></p>
+
+<p>当用户点击按钮弹出菜单显示,当用户点击弹出菜单外的任何区域弹出菜单关闭。可以使用  <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/close">window.close()</a></code> 来关闭弹出菜单。</p>
+
+<p>你可以使用专门的在manifest.json中使用"_execute_browser_action" 和 "_execute_page_action" 来定义一个快捷键打开浏览器行为或页面行为. 详情请看 <code><a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/commands">commands</a></code> manifest.json 关键字。不过你不能在你的扩展脚本中通过编程打开弹出菜单 : 他只能通过用户的行为的被打开。</p>
+
+<p>弹出菜单像普通网页一样通过HTML文件被定义,你当然也可以在里面包含CSS 和 javascript文件。 而且不像普通网页, 其包含的javascript可以使用所有的已经通过<a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions">permissions</a>获取了使用权限的 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API">WebExtension APIs</a> 。</p>
+
+<p>你可以要求浏览器在你的弹出菜单中包含一个样式表以使其看起来与浏览器UI一致。为了达成这一目的,在你的 <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_action">browser_action</a></code> 或 <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/page_action">page_action</a>  关键字中包含<code> "browser_style": true</code> 。</p>
+
+<p>弹出菜单存在一个限制其可以加载资源的源地址的安全机制, 同时不允许类似 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval">eval()</a></code> 的做法的使用 查看 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy">Content Security Policy</a> 获取更多细节。</p>
+
+<p>你可以使用Add-on Debugger来调试弹出菜单标记和脚本,但是你需要一些技巧来设置让弹出菜单不在自动关闭。<a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Debugging#Debugging_popups"> 阅读关于调试弹出菜单</a>。</p>
+
+<h3 id="弹出菜单尺寸重新计算">弹出菜单尺寸重新计算</h3>
+
+<p>弹出菜单自动根据其内容调整尺寸。其适应算法可能因浏览器而不同。</p>
+
+<p>在火狐, 尺寸只再弹出菜单显示前被计算,而且在内容变化后至多进行每秒十次的计算。严格来说, 尺寸受 <code><a href="/en-US/docs/Web/HTML/Element/body">&lt;body&gt;</a></code> 元素放置尺寸决定。 一种怪异的说法是, 他由 <code><a href="/en-US/docs/Web/HTML/Element/html">&lt;html&gt;</a></code> 决定, Firefox 计算该元素的推荐宽度, 重新调整弹出菜单至其宽度, 然后完成尺寸调整所以这里没有上下滚动。 如果适应用户的屏幕他可能会增长到800X600px的尺寸。 如果用户 <a href="https://support.mozilla.org/en-US/kb/customize-firefox-controls-buttons-and-toolbars#w_customize-the-menu-or-the-toolbar">移动弹出菜单对应按钮到菜单面板</a> ,而后弹出菜单会在菜单栏内显示并具有合适的尺寸。</p>
+
+<h2 id="设置页面">设置页面</h2>
+
+<p>设置页面允许你定义你的扩展可以被用户修改的选项。 用户从浏览器扩展管理器中访问设置页面:</p>
+
+<p>{{EmbedYouTube("02oXAcbUv-s")}}</p>
+
+<p>每个浏览器访问该页面的方法存在区别。</p>
+
+<ul>
+</ul>
+
+<p>你可以通过调用 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/Runtime/openOptionsPage" title="If your add-on does not have an options page, or the browser failed to create one for some other reason, runtime.lastError will be set."><code>runtime.openOptionsPage()</code></a> 打开设置页面</p>
+
+<p>设置页面存在一个限制其可以加载资源的源地址的安全机制, 同时不允许类似 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval">eval()</a></code> 的做法的使用 查看 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_Security_Policy">Content Security Policy</a> 获取更多细节。</p>
+
+<h3 id="定义一个设置页面:">定义一个设置页面:</h3>
+
+<p>创建一个设置页面有以下流程:</p>
+
+<ul>
+ <li>写一个HTML文件定义页面。该文件像普通网页一样可以包含CSS和Javascript 文件而且可以使用所有 <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API">WebExtension APIs</a> ,特别的你可以使用 <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/Storage" title="Enables WebExtensions to store and retrieve data, and listen for changes to stored items."><code>storage</code></a> API 来保存设置。</li>
+ <li>将这些文件打包至你的扩展。</li>
+ <li>在manifest.json 文件包含 <code><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/options_ui">options_ui</a></code> 关键字, 并给予设置页面的URL。</li>
+</ul>
+
+<h3 id="例子_3">例子</h3>
+
+<p> <a href="https://github.com/mdn/webextensions-examples/tree/master/favourite-colour">favourite-colour</a> 使用了设置页面。</p>
+
+<h2 id="上下文菜单项">上下文菜单项</h2>
+
+<p>使用 {{WebExtAPIRef("contextMenus")}} API, 你可以按你指定的情况向浏览器上下文菜单添加项目, 比如,你可以只在用户点击图片时显示一项,或者在一个可编辑的元素上,或者被选择的页面的一部份。</p>
+
+<h3 id="指定一个上下文菜单项">指定一个上下文菜单项</h3>
+
+<p>您可以使用{{WebExtAPIRef("contextMenus")}} API来 程序化地管理上下文菜单项。</p>
+
+<h3 id="例子_4">例子</h3>
+
+<p> <a href="https://github.com/mdn/webextensions-examples/tree/master/context-menu-demo">context-menu-demo</a> 创建了几种不同的上下文菜单项。</p>
+
+<h2 id="通知">通知</h2>
+
+<p>使用 {{WebExtAPIRef("notifications")}} API,你通过使用操作系统的通知系统可以创建短时通知:</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/14043/notify-shadowed.png" style="display: block; height: 334px; margin-left: auto; margin-right: auto; width: 700px;"></p>
+
+<h3 id="定义一个通知">定义一个通知</h3>
+
+<p>使用{{WebExtAPIRef("notifications")}} API 可以程序化地管理通知。</p>
+
+<h3 id="Examples">Examples</h3>
+
+<p><a href="https://github.com/mdn/webextensions-examples/tree/master/notify-link-clicks-i18n">notify-link-clicks-i18n</a> 创建了通知。</p>
diff --git a/files/zh-cn/mozilla/add-ons/working_with_multiprocess_firefox/index.html b/files/zh-cn/mozilla/add-ons/working_with_multiprocess_firefox/index.html
new file mode 100644
index 0000000000..152a15de20
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/working_with_multiprocess_firefox/index.html
@@ -0,0 +1,296 @@
+---
+title: 编写适合多进程 Firefox 的扩展
+slug: Mozilla/Add-ons/Working_with_multiprocess_Firefox
+translation_of: Archive/Add-ons/Working_with_multiprocess_Firefox
+---
+<div class="summary">
+<p>致 Firefox 开发者:本文描述如何使你开发的扩展能在多进程 Firefox 中运行。</p>
+</div>
+
+<p>目前,在桌面版 Firefox 中,Chrome 代码(Chrome Code)和内容(Content)运行在同一个进程里。因此扩展可以直接访问网页内容:</p>
+
+<pre class="brush: js">gBrowser.selectedBrowser.contentDocument.body.innerHTML = "replaced by chrome code";</pre>
+
+<p>不过呢,在多进程 Firefox(又称 Electrolysis 或 E10S)中,扩展代码(Add-on Code)和内容则在不同的进程中运行,所以上述直接访问就不一定可行了。</p>
+
+<p>在多进程 Firefox 中,扩展需要将触及内容的代码分解成单独分离的脚本,也就是所谓的框架脚本(Frame Scripts)。框架脚本在内容进程中运行,可以直接访问内容。框架脚本通过消息传递接口(Message-passing API)与扩展的剩余部分进行通讯。</p>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/8437/e10s-overview.png" style="display: block; margin-left: auto; margin-right: auto;">运行在 Chrome 进程中的扩展代码必须向框架脚本发送异步消息。这样做可以确保 Firefox 的用户界面不会被内容进程卡死。</p>
+
+<p>内容进程则可以向 Chrome 进程发送同步或异步消息,不过使用异步消息是再好不过了。</p>
+
+<p>关于使用消息管理器的更多细节,请参阅:<a href="/zh-CN/docs/The_message_manager">消息管理器指南</a>。接下来,本文将告诉你如何判断你开发的扩展是否会受到这方面的影响,同时简要说明需要如何进行修改。最后,通过对一些简单的样板扩展进行修改,让它们能在多进程 Firefox 中运行。</p>
+
+<h2 id="检查你的扩展是否受到影响">检查你的扩展是否受到影响</h2>
+
+<p>总体规则如下:</p>
+
+<ul>
+ <li>如果你只是使用附加组件开发工具包的<a href="https://developer.mozilla.org/zh-CN/Add-ons/SDK/High-Level_APIs">高级接口</a>,你的扩展不会受到影响(附加组件开发工具包尚未完全兼容多进程Firefox,但很快就会完全兼容)。</li>
+ <li>如果你的扩展完全不访问网络内容,它们也不会受到影响。</li>
+ <li>如果你通过直接使用<a href="https://developer.mozilla.org/zh-CN/Add-ons/Overlay_Extensions">表层扩展</a>、<a href="https://developer.mozilla.org/zh-CN/Add-ons/Bootstrapped_extensions">启动扩展</a>或<a href="https://developer.mozilla.org/zh-CN/Add-ons/SDK/Low-Level_APIs">底层开发工具包接口</a>(例如<a href="https://developer.mozilla.org/zh-CN/Add-ons/SDK/Low-Level_APIs/window_utils">窗口/工具</a>或<a href="https://developer.mozilla.org/zh-CN/Add-ons/SDK/Low-Level_APIs/tabs_utils">标签页/工具</a>)来访问网络内容,那么你的扩展有可能受到影响。</li>
+ <li>如果你在标签页中加载可扩展用户界面语言(xul),你的扩展会受到影响。</li>
+</ul>
+
+<p>为了证实是否受到影响,你还需要进一步测试,这个测试过程由两步过程构成:</p>
+
+<ul>
+ <li><strong>开启 Firefox 的多进程支持</strong>:<a href="https://nightly.mozilla.org/">Firefox 每夜版</a>(Nightly Build)支持多进程,但是默认是关闭的,而且并没有出现在选项窗口中。启用多进程的方法是访问 about:config 页面,找到名为 browser.tabs.remote.autostart 的项目,将其值设置为true,重启火狐浏览器。启用多进程功能后,标签页的标题会出现下划线以提示用户。</li>
+ <li><strong>声明你的扩展兼容多进程模式</strong>:为了便于迁移至多进程 Firefox,我们提供<a href="https://developer.mozilla.org/zh-CN/Firefox/Multiprocess_Firefox/Compatibility_shims">兼容性管理工具</a>帮助不兼容多进程的扩展工作。故此,你需要禁用兼容性管理工具以检测你的扩展是否真正兼容。禁用兼容性管理工具的方法是向你的扩展的 install.rdf 文件添加一个名为 multiprocessCompatible 的属性,值为 true。</li>
+</ul>
+
+<p>现在,你可以在多进程 Firefox 中禁用兼容性管理工具来测试你的扩展的兼容性了。可惜你还不能在开启多进程功能的时候安装新扩展,因此你必须先安装好扩展再开启多进程功能。关于这个问题,详见 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1055808">bug 1055808</a>。</p>
+
+<h2 id="更新你的代码">更新你的代码</h2>
+
+<p>更新代码的一般方法是:</p>
+
+<ul>
+ <li>将你的扩展中需要访问网络内容的部分分解为一个或数个单独的脚本。在多进程Firefox中,这被称为框架脚本。</li>
+ <li>为你的框架脚本注册 chrome:// 地址。</li>
+ <li>用<a href="https://developer.mozilla.org/zh-CN/docs/The_message_manager">消息管理器</a>来将脚本加载进 <a href="https://developer.mozilla.org/zh-CN/docs/Mozilla/Tech/XUL/browser"><code>browser </code></a>对象。</li>
+ <li>如果你的扩展需要在主扩展代码和框架脚本之间通信,可以使用消息管理器接口来实现。</li>
+ <li>如果你需要在标签页中加载可扩展用户界面语言,可以将它们注册为 about: 地址,然后通过 about: 地址加载它们。</li>
+</ul>
+
+<p>更多细节,请参见<a href="/zh-CN/docs/The_message_manager"> message manager</a> 文档。</p>
+
+<h3 id="新应用程序接口的向前兼容能力">新应用程序接口的向前兼容能力</h3>
+
+<p>新的多进程 Firefox 的消息接口在多进程模式没有开启的情况下仍然可用。实际上它们从 Firefox 4开始就在某种程度上可用了。不过呢,最初的应用程序接口和现在的并不相同。一些已知的差异如下:</p>
+
+<ul>
+ <li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=776825">Firefox 17 的界面发生了变化</a>。</li>
+ <li>在Firefox 19 之前的版本中,类似<code>new content.document.defaultView.XMLHttpRequest()</code>的代码会得到<code>NS_ERROR_FAILURE: Failure</code>的错误值。</li>
+</ul>
+
+<p>你不仅应该在开启了多进程支持的每夜版Firefox上测试你的扩展的变化,而且应该在你打算支持的没有开启多进程支持的发行版(Release Build)中测试。</p>
+
+<h2 id="举几个例子">举几个例子</h2>
+
+<p>这部分将演示修改几种不同的扩展的过程。这些扩展都是很简易的,意在展示基础的扩展模式在多进程Firefox中需要的不同处理方式。</p>
+
+<p>你可以在 <a href="https://github.com/mdn/e10s-example-addons">e10s-example-addons GitHub repository</a> 中找到这些例子的所有源代码。</p>
+
+<h3 id="在所有页面运行一个脚本">在所有页面运行一个脚本</h3>
+
+<div class="note">
+<p><a href="https://github.com/mdn/e10s-example-addons/tree/master/run-script-in-all-pages">查看这个例子的源代码</a></p>
+</div>
+
+<p>第一个扩展在每一个页面加载的时候运行一些代码。这些代码不和扩展的其他部分交互,它们只是对页面进行一些预设的修改。在这个例子中,扩展向文档的主体(<a href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/body"><code>body</code></a>)添加了一个边界。</p>
+
+<p>这个扩展通过将一种“页面加载中”代码碎片(<a href="https://developer.mozilla.org/zh-CN/docs/Code_snippets/On_page_load#Basic_onPageLoad_for_a_browser_window">"On page load" code snippet</a>)附加于可扩展用户界面语言层来实现此修改。</p>
+
+<pre class="brush: js">var myExtension = {
+ init: function() {
+ // The event can be DOMContentLoaded, pageshow, pagehide, load or unload.
+ if(gBrowser) gBrowser.addEventListener("DOMContentLoaded", this.onPageLoad, false);
+ },
+ onPageLoad: function(aEvent) {
+ var doc = aEvent.originalTarget; // doc is document that triggered the event
+ if (doc.nodeName != "#document") return; // only documents
+ // make whatever modifications you want to doc
+ doc.body.style.border = "5px solid blue";
+ }
+}
+
+window.addEventListener("load", function load(event){
+ window.removeEventListener("load", load, false); //remove listener, no longer needed
+ myExtension.init();
+},false);</pre>
+
+<p>因为这段代码直接访问网络内容,所以它不能在多进程 Firefox 中运行。<br>
+ <img alt="" src="https://mdn.mozillademos.org/files/8431/all-pages-original.png" style="display: block; margin-left: auto; margin-right: auto;"></p>
+
+<h4 id="移植到消息管理器">移植到消息管理器</h4>
+
+<p>为了使用消息管理器移植这个例子,我们可将这个扩展全部的主体部分放入一个框架脚本:</p>
+
+<pre class="brush: js">// frame-script.js
+// will run in the content process
+
+addEventListener("DOMContentLoaded", function(event) {
+ var doc = event.originalTarget;
+ if (doc.nodeName != "#document") return; // only documents
+ doc.body.style.border = "5px solid red";
+});
+</pre>
+
+<p>我们将为这个框架脚本注册一个 chrome:// URL :</p>
+
+<pre>// chrome.manifest
+
+content    modify-all-pages    chrome/content/
+</pre>
+
+<p>我们附加到XUL overlay的主体脚本,只是一个使用全局消息管理器来在每个标签页中加载框架脚本的 stub。</p>
+
+<pre class="brush: js">// chrome script
+// will run in the chrome process
+
+var globalMM = Cc["@mozilla.org/globalmessagemanager;1"]
+ .getService(Ci.nsIMessageListenerManager);
+
+globalMM.loadFrameScript("chrome://modify-all-pages/content/frame-script.js", true);</pre>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/8415/all-pages-ported.png" style="display: block; margin-left: auto; margin-right: auto;"></p>
+
+<h4 id="移植到_Add-on_SDK">移植到 Add-on SDK</h4>
+
+<p>一个好的替代这样的一个扩展的思路是将其移植到 Add-on SDK。Add-on SDK 包括一个名为 <a href="/zh-CN/Add-ons/SDK/High-Level_APIs/page-mod">page-mod</a> 的设计为在网页中加载脚本的模块。Add-on SDK 称这些脚本为内容脚本。</p>
+
+<p>这种情况下扩展的主要代码创建一个 page-mod 来加载内容脚本到用户载入的每个页面:</p>
+
+<pre class="brush: js">// main.js
+
+var pageMod = require("sdk/page-mod");
+var self = require("sdk/self");
+
+pageMod.PageMod({
+ include: "*",
+ contentScriptFile: self.data.url("modify-all-pages.js")
+});</pre>
+
+<p>内容脚本可以直接修改页面:</p>
+
+<pre class="brush: js">// modify-all-pages.js - content script
+
+document.body.style.border = "5px solid green";</pre>
+
+<h3 id="在活动标签中运行一个脚本">在活动标签中运行一个脚本</h3>
+
+<div class="note">
+<p><a href="https://github.com/mdn/e10s-example-addons/tree/master/run-script-in-active-page">查看这个例子的代码。</a></p>
+</div>
+
+<p>这个例子说明了一个扩展如何:</p>
+
+<ul>
+ <li><a href="/zh-CN/docs/The_message_manager#Types_of_message_manager">向一个特定的XUL &lt;browser&gt; 元素中加载框架脚本</a></li>
+ <li><a href="/zh-CN/docs/The_message_manager#Synchronous_messaging">从框架脚本向扩展主体发出一个同步的请求</a></li>
+</ul>
+
+<p>这个例子是一个无需重启的扩展,它使用 CustomizableUI 模块添加了一个按钮。当用户点击这个按钮,这个扩展运行一些代码来改变当前标签。其基础构造取自 <a href="https://github.com/jvillalobos/Australis-Hello-World">Jorge Villalobos 的 Australis "Hello World" 扩展</a> .<br>
+ <br>
+ 代码实际做的事是:找到任意 <code><a href="/zh-CN/docs/Web/HTML/Element/Img">&lt;img&gt;</a></code> 元素并将其 <code>src</code> 替换为从硬编码于扩展中的列表中随机抽取的无意义的 GIF 图像。 无意义的 gifs 从<a href="https://github.com/bwinton/whimsy">Whimsy extension </a>获取。</p>
+
+<p>第一个版本直接访问页面,因此其不是多进程兼容的:</p>
+
+<pre class="brush: js">// bootstrap.js
+
+let Gifinate = {
+ init : function() {
+ let io =
+ Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+
+ // the 'style' directive isn't supported in chrome.manifest for bootstrapped
+ // extensions, so this is the manual way of doing the same.
+ this._ss =
+ Cc["@mozilla.org/content/style-sheet-service;1"].
+ getService(Ci.nsIStyleSheetService);
+ this._uri = io.newURI("chrome://gifinate/skin/toolbar.css", null, null);
+ this._ss.loadAndRegisterSheet(this._uri, this._ss.USER_SHEET);
+
+ // create widget and add it to the main toolbar.
+ CustomizableUI.createWidget(
+ { id : "gifinate-button",
+ defaultArea : CustomizableUI.AREA_NAVBAR,
+ label : "Gifinate",
+ tooltiptext : "Gifinate!",
+ onCommand : function(aEvent) {
+ Gifinate.replaceImages(aEvent.target.ownerDocument.defaultView.content.document);
+ }
+ });
+ },
+
+ replaceImages : function(contentDocument) {
+ let images = contentDocument.getElementsByTagName("img");
+ for (var i = 0; i &lt; images.length; ++i) {
+ let gif = this.gifs[Math.floor(Math.random() * this.gifs.length)];
+ images[i].src = gif;
+ }
+ },</pre>
+
+<p><img alt="" src="https://mdn.mozillademos.org/files/8433/gifinate-original.png" style="display: block; margin-left: auto; margin-right: auto;"></p>
+
+<h4 id="移植到消息管理器_2">移植到消息管理器</h4>
+
+<p>为了移植这个例子到消息管理器,我们将使 <code>onCommand</code> 加载一个框架脚本到当前的 <code>&lt;browser&gt;</code>,然后监听来自框架脚本的 "request-gifs" 信息。这些 "request-gifs" 信息应当包含我们在此页面上需要的 GIFs :信息监听器取回并返回这个数量的 GIFs。</p>
+
+<pre class="brush: js">// bootstrap.js
+// will run in the chrome process
+
+let Gifinate = {
+ init : function() {
+ let io =
+ Cc["@mozilla.org/network/io-service;1"].
+ getService(Ci.nsIIOService);
+
+ // the 'style' directive isn't supported in chrome.manifest for bootstrapped
+ // extensions, so this is the manual way of doing the same.
+ this._ss =
+ Cc["@mozilla.org/content/style-sheet-service;1"].
+ getService(Ci.nsIStyleSheetService);
+ this._uri = io.newURI("chrome://gifinate/skin/toolbar.css", null, null);
+ this._ss.loadAndRegisterSheet(this._uri, this._ss.USER_SHEET);
+
+ // create widget and add it to the main toolbar.
+ CustomizableUI.createWidget(
+ { id : "gifinate-button",
+ defaultArea : CustomizableUI.AREA_NAVBAR,
+ label : "Gifinate Button",
+ tooltiptext : "Gifinate!",
+ onCommand : function(aEvent) {
+ Gifinate.replaceImages(aEvent.target.ownerDocument);
+ }
+ });
+ },
+
+ replaceImages : function(xulDocument) {
+ var browserMM = xulDocument.defaultView.gBrowser.selectedBrowser.messageManager;
+ browserMM.loadFrameScript("chrome://gifinate/content/frame-script.js", false);
+ browserMM.addMessageListener("request-gifs", Gifinate.getGifs);
+ },
+
+ getGifs : function(message) {
+ var gifsToReturn = new Array(message.data);
+ for (var i = 0; i &lt; gifsToReturn.length; i++) {
+ let gif = this.gifs[Math.floor(Math.random() * this.gifs.length)];
+ gifsToReturn[i] = gif;
+ }
+ return gifsToReturn;
+ },
+</pre>
+
+<p>再次地,我们需要为这个框架脚本注册一个 chrome:// URL:</p>
+
+<pre>// chrome.manifest
+
+content gifinate frame-script.js</pre>
+
+<p>在框架脚本中,我们获取所有的 <code>&lt;img&gt;</code> 元素并发送 "request-gifs" 信息给扩展主体代码。 由于这是框架脚本我们可以将其变为一个同步信息,并使用其返回值更新 <code>src</code> 属性:</p>
+
+<pre class="brush: js">// frame-script.js
+// will run in the content process
+
+var images = content.document.getElementsByTagName("img");
+var response = sendSyncMessage("request-gifs", images.length);
+var gifs = response[0];
+
+for (var i = 0; i &lt; images.length; ++i) {
+ images[i].src = gifs[i];
+}</pre>
+
+<p>整个扩展的流程现在像这样:<br>
+ <img alt="" src="https://mdn.mozillademos.org/files/8411/gifinate-ported.png" style="display: block; margin-left: auto; margin-right: auto;"></p>
+
+<h2 id="已知问题">已知问题</h2>
+
+<p>这里是可能影响扩展开发者移植到多进程firefox的开放的bug列表:</p>
+
+<ul>
+ <li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1051238"><strong>Bug 1051238</strong></a> -<span id="summary_alias_container"> 框架脚本被永久缓存,因此扩展不能在不重启浏览器的情况下正确更新</span></li>
+ <li><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1017320"><strong>Bug 1017320</strong></a> -<span id="summary_alias_container"> 实施兼容shims的跟踪<span id="short_desc_nonedit_display"> bug</span></span></li>
+</ul>
diff --git a/files/zh-cn/mozilla/add-ons/雷鸟/index.html b/files/zh-cn/mozilla/add-ons/雷鸟/index.html
new file mode 100644
index 0000000000..c46b242f7e
--- /dev/null
+++ b/files/zh-cn/mozilla/add-ons/雷鸟/index.html
@@ -0,0 +1,131 @@
+---
+title: 雷鸟扩展
+slug: Mozilla/Add-ons/雷鸟
+translation_of: Mozilla/Thunderbird/Thunderbird_extensions
+---
+<div class="callout-box"><strong><a href="/en/Extensions/Thunderbird/Building_a_Thunderbird_extension" title="en/Building_a_Thunderbird_extension">Building a Thunderbird extension</a></strong><br>
+Step-by-step explanation on how to build an extension for Thunderbird.</div>
+
+<div>
+<p>{{AddonSidebar}}</p>
+本文档是为Mozilla公司的雷鸟邮件客户端开发扩展的教程。Although there are many similarities with <a href="/en/Extensions" title="en/Extensions">Firefox extensions</a> there are also some differences that may confound the starting developer.</div>
+
+<div><br>
+<strong>Please help!</strong> You can <a class="internal" href="/en/Extensions/Thunderbird/HowTos" title="en/Extensions/Thunderbird/HowTos">add a how-to</a> (a question or an answer or a code snippet), <a class="internal" href="/en/Extensions/Thunderbird/Useful_newsgroups_discussions" title="En/Extensions/Thunderbird/Useful newsgroups discussions">summarize and link to a relevant newsgroup discussion</a>, or create a tutorial. Need help? Contact <a class="internal" href="/User:jenzed" title="User:jenzed">jenzed</a>.</div>
+
+<table class="topicpage-table">
+ <tbody>
+ <tr>
+ <td>
+ <h2 id="Documentation" name="Documentation"><a href="/Special:Tags?tag=Extensions&amp;language=en" title="Special:Tags?tag=Extensions&amp;language=en">Documentation</a></h2>
+
+ <h3 id="Getting_started_with_Thunderbird">Getting started with Thunderbird</h3>
+
+ <p>A brave, young developer wants to develop an add-on for Thunderbird. Here's a few links to help them through this journey.</p>
+
+ <ul>
+ <li>Start by reading the tutorial and learn how to<a class="internal" href="/en/Extensions/Thunderbird/Building_a_Thunderbird_extension" title="En/Building a Thunderbird extension"> build a Thunderbird extension</a> (Outdated, still talks about overlays and the add-on builder is no longer available but the tutorial has not been updated.)</li>
+ <li>Read about the <a href="/en/Thunderbird/Main_Windows" title="Main Windows">main windows</a> so that you know what one means when they say « thread pane », « preview pane », and « folder pane ».</li>
+ <li>Read an <a class="external" href="http://blog.xulforum.org/index.php?post/2011/01/03/An-overview-of-Thunderbird-Conversations" title="http://blog.xulforum.org/index.php?post/2011/01/03/An-overview-of-Thunderbird-Conversations">overview</a> of how the various parts of Thunderbird fit together, this really helps get a better understanding of Thunderbird.</li>
+ <li>Want to do some real stuff? See <a class="external" href="http://blog.xulforum.org/index.php?post/2011/03/14/Basic-MimeMessage-demo" title="http://blog.xulforum.org/index.php?post/2011/03/14/Basic-MimeMessage-demo">how to inspect a message</a> (demo add-on included!)</li>
+ <li>Play with our other <a href="/en/Extensions/Thunderbird/Demo_Addon" title="Demo Addon">demo add-on</a> that exercises some more advanced Thunderbird-specific features</li>
+ <li>Want to do even more stuff? Don't reinvent the wheel: steal functions from the <a class="link-https" href="https://github.com/protz/thunderbird-stdlib" title="https://github.com/protz/thunderbird-stdlib">thunderbird-stdlib</a> project (doc <a class="external" href="http://protz.github.com/thunderbird-stdlib/doc/symbols/_global_.html" title="http://protz.github.com/thunderbird-stdlib/doc/symbols/_global_.html">here</a>). Functions for dealing with messages (delete them, archive them, change their tags, etc.) are included.</li>
+ <li>Haven't found what you're looking for? Read the <a class="internal" href="/en/Extensions/Thunderbird/HowTos" rel="internal" title="en/Extensions/Thunderbird/HowTos">Thunderbird how-tos</a>; they contain a lot of recipes for things extensions want to do.</li>
+ <li>Still haven't managed to do what you wanted? See the list of all <a class="external" href="http://wiki.mozilla.org/Thunderbird/CommunicationChannels" title="http://wiki.mozilla.org/Thunderbird/CommunicationChannels">Thunderbird communication channels </a>so that you know where to ask when you get stuck :-).</li>
+ <li>Feeling really brave? Read the source using a <a class="external" href="http://doxygen.db48x.net/comm-central/html/" title="http://doxygen.db48x.net/comm-central/html/">fancy interface</a>; you can often find tests that demonstrate how to do what you're trying to achieve.</li>
+ </ul>
+
+ <h3 id="The_Gloda_database">The Gloda database</h3>
+
+ <p>Thunderbird has a subsystem called Gloda. Gloda stands for « Global Database », and creates Thunderbird-wide relations between objects. Gloda provides concepts such as Conversations, Messages, Identities, Contacts. All these concepts are related together: a Conversation contains Messages which are linked to Identities (<strong>from</strong> field, <strong>to</strong> field) which are themselves part of a Contact: indeed, a contact has multiple identities.</p>
+
+ <p>Typical use cases for Gloda: find all messages whose subject matches [search term], find all messages from [person], find all messages in the same thread as [a given message], find all messages involving [person], etc. etc.</p>
+
+ <p>Gloda is extremely powerful and is used heavily by add-ons such as <a class="link-https" href="https://addons.mozilla.org/en-US/thunderbird/addon/gmail-conversation-view/" title="https://addons.mozilla.org/en-US/thunderbird/addon/gmail-conversation-view/">Thunderbird Conversations</a>. Learn more about Gloda:</p>
+
+ <ul>
+ <li>an overview of <a href="/en/Thunderbird/gloda" title="Gloda">Gloda</a></li>
+ <li>learn how to create <a href="/en/Thunderbird/Creating_a_Gloda_message_query" title="Creating a gloda message query">your first message query</a> and read the <a href="/en/Thunderbird/Gloda_examples" title="Gloda examples">gloda examples</a></li>
+ <li>learn about the Gloda internals: <a href="/en/Thunderbird/Gloda_debugging" title="Gloda debugging">Gloda debugging</a>, <a href="/en/Thunderbird/Gloda_indexing" title="Gloda indexing">Gloda indexing</a></li>
+ </ul>
+
+ <h3 id="More_Thunderbird-specific_links">More Thunderbird-specific links</h3>
+
+ <p>Some of these links may be wildly out of date, but they still provide valuable information on the codebase.</p>
+
+ <ul>
+ <li><a class="internal" href="/en/Extensions/Thunderbird/An_overview_of_the_Thunderbird_interface" title="En/Extensions/Thunderbird/An overview of the Thunderbird interface">An overview of Thunderbird components</a></li>
+ <li><a class="internal" href="/en/Extensions/Thunderbird/Thunderbird_developer_reference_docs" title="en/Extensions/Thunderbird/Thunderbird developer reference docs">Developer reference docs</a>:
+ <ul>
+ <li><a class="internal" href="/en/Folders" title="En/Folders">Folder classes</a></li>
+ <li><a class="internal" href="/en/DB_Views_(message_lists)" title="En/DB Views (message lists)">DB views (message list)</a></li>
+ <li><a class="internal" href="/en/Message_Summary_Database" title="En/Message Summary Database">Message summary database</a></li>
+ <li><a class="internal" href="/en/MailNews_Protocols" title="En/MailNews Protocols">MailNews protocols</a></li>
+ <li><a class="internal" href="/En/MailNews_Filters" rel="internal" title="En/MailNews Filters">MailNews filters</a></li>
+ <li><a class="internal" href="/en/Extensions/Thunderbird/Error_reporting_tools" title="en/Extension Library/Extensions/Thunderbird/Error reporting tools">Error reporting tools</a></li>
+ <li><a href="/en/Toolkit_API/STEEL" title="en/Toolkit API/STEEL">STEEL library</a> (not actively developed anymore, use   <a class="link-https" href="https://github.com/protz/thunderbird-stdlib" title="https://github.com/protz/thunderbird-stdlib">https://github.com/protz/thunderbird-stdlib</a>)</li>
+ <li><a class="external" href="http://quetzalcoatal.blogspot.com/2010/01/developing-new-account-types-part-0.html" title="http://quetzalcoatal.blogspot.com/2010/01/developing-new-account-types-part-0.html">Developing new account types</a> <strong>NEW!</strong></li>
+ </ul>
+ </li>
+ <li><a class="internal" href="/en/Extensions/Thunderbird/Useful_newsgroups_discussions" title="En/Extensions/Thunderbird/Useful newsgroups discussions">Useful newsgroup discussions</a> (watch out, anything that's too old should be regarded suspiciously; there's been significant API rewrite over the past years, and most of these techniques are considerably easier now) </li>
+ <li><a href="/en/Thunderbird/Thunderbird_API_documentation" title="en/Thunderbird/Thunderbird API documentation">Thunderbird API docs</a> (mostly a collection of out-of-date pages, relevance is rather dubious) </li>
+ <li><a href="/En/Thunderbird_3_for_developers" title="En/Thunderbird 3 for developers">Thunderbird 3 for developers</a> and <a href="/en/Thunderbird_3.1_for_developers" title="en/Thunderbird 3.1 for developers">Thunderbird 3.1 for developers</a> - changes in the recent Thunderbird updates affecting add-on developers. <a href="/Thunderbird_5_for_developers" title="Thunderbird 5 for developers">Thunderbird 5 for developers</a> has important information on MsgHdrToMimeMessage which is a central piece of code.</li>
+ </ul>
+
+ <h3 id="General_links">General links</h3>
+
+ <ul>
+ <li><a class="internal" href="/en/Extensions" title="en/Extensions">General information on developing extensions for Mozilla applications</a></li>
+ <li><a href="/en/Extensions/Thunderbird/Finding_the_code_for_a_feature" title="en/Extensions/Thunderbird/Finding the code for a feature">Finding the code for a feature</a></li>
+ <li><a class="external" href="http://kb.mozillazine.org/Category:Thunderbird" title="http://kb.mozillazine.org/Category:Thunderbird">Mozillazine articles on Thunderbird</a></li>
+ <li><a href="/Special:Tags?tag=Thunderbird" title="https://developer.mozilla.org/Special:Tags?tag=Thunderbird">All pages tagged with Thunderbird</a></li>
+ <li><a href="/Special:Tags?tag=MailNews" title="https://developer.mozilla.org/Special:Tags?tag=MailNews">All pages tagged with MailNews</a></li>
+ </ul>
+ </td>
+ <td>
+ <h2 id="Community" name="Community">Community</h2>
+
+ <ul>
+ <li>See the list of all <a class="external" href="http://wiki.mozilla.org/Thunderbird/CommunicationChannels" title="http://wiki.mozilla.org/Thunderbird/CommunicationChannels">Thunderbird communication channels </a>first</li>
+ <li>Among these are:</li>
+ </ul>
+
+ <p>{{ DiscussionList("dev-extensions", "mozilla.dev.extensions") }}</p>
+
+ <ul>
+ <li><a class="link-irc" href="irc://moznet/#extdev">#extdev IRC channel</a> / <a class="link-irc" href="irc://moznet/#maildev">#maildev IRC channel</a></li>
+ <li><a class="external" href="http://forums.mozillazine.org/viewforum.php?f=19">MozillaZine forum</a></li>
+ <li><a class="external" href="http://mozdev.org/mailman/listinfo/project_owners">mozdev project owners</a></li>
+ <li><a href="/en/Extensions/Community" title="en/Extensions/Community">Other community links...</a></li>
+ </ul>
+
+ <h2 id="Tools" name="Tools">Tools</h2>
+
+ <ul>
+ <li><a class="link-https" href="https://addons.mozilla.org/en-US/firefox/addon/6622" rel="external nofollow" title="https://addons.mozilla.org/en-US/firefox/addon/6622">DOM Inspector</a> edit the live DOM (Firefox and Thunderbird)</li>
+ <li><a class="link-https" href="https://addons.mozilla.org/thunderbird/addon/workspace-for-thunderbird/" title="https://addons.mozilla.org/thunderbird/addon/workspace-for-thunderbird/">Workspace for Thunderbird</a>, allows running code snippets in Thunderbird and inspecting variable structure and content</li>
+ <li><a class="external" href="http://www.hacksrus.com/~ginda/venkman/" rel="external nofollow" title="http://www.hacksrus.com/~ginda/venkman/">Venkman</a>, a JavaScript debugger (<a class="external" href="http://addons.mozilla.org/en-US/firefox/addon/216" rel="external nofollow" title="http://addons.mozilla.org/en-US/firefox/addon/216">Firefox</a>, <a class="external" href="http://addons.mozilla.org/en-US/thunderbird/addon/216" rel="external nofollow" title="http://addons.mozilla.org/en-US/thunderbird/addon/216">Thunderbird</a>)</li>
+ <li><a class="link-https" href="https://addons.mozilla.org/en-US/firefox/addon/7434/" rel="external nofollow" title="https://addons.mozilla.org/en-US/firefox/addon/7434/">Extension Developer's Extension</a> a suite of development tools</li>
+ <li><a class="external" href="http://www.gijsk.com/" rel="external nofollow" title="http://www.gijsk.com/">Chrome List</a> view files in chrome:// (<a class="external" href="http://addons.mozilla.org/en-US/firefox/addon/4453" rel="external nofollow" title="http://addons.mozilla.org/en-US/firefox/addon/4453">Firefox</a>, <a class="external" href="http://addons.mozilla.org/en-US/thunderbird/addon/4453" rel="external nofollow" title="http://addons.mozilla.org/en-US/thunderbird/addon/4453">Thunderbird</a>)</li>
+ <li><a class="external" href="http://addons.mozilla.org/en-US/developers/tools/builder" rel="external nofollow" title="http://addons.mozilla.org/en-US/developers/tools/builder">Add-on Builder</a> a web-based extension skeleton generator (Firefox and Thunderbird)</li>
+ <li><a href="/en/Mozmill" title="en/Mozmill">Mozmill</a> test tool and framework</li>
+ <li><a class="external" href="http://xpcomviewer.mozdev.org/" rel="external nofollow" title="http://xpcomviewer.mozdev.org">XPCOMViewer</a> an XPCOM inspector (Firefox and Thunderbird)</li>
+ </ul>
+
+ <p>... <a class="internal" href="/en/Setting_up_extension_development_environment#Development_extensions" title="en/Setting up extension development environment#Development extensions">more tools</a> ...</p>
+
+ <p><span class="alllinks"><a href="/Special:Tags?tag=Extensions:Tools&amp;language=en" title="Special:Tags?tag=Extensions:Tools&amp;language=en">View All...</a></span></p>
+
+ <h2 id="Related_Topics" name="Related_Topics">Related Topics</h2>
+
+ <dl>
+ <dd><a href="/en/XUL" title="en/XUL">XUL</a>, <a href="/en/JavaScript" title="en/JavaScript">JavaScript</a>, <a href="/en/XPCOM" title="en/XPCOM">XPCOM</a>, <a href="/en/Themes" title="en/Themes">Themes</a>, <a href="/En/Developer_Guide" title="en/Developing_Mozilla">Developing Mozilla</a></dd>
+ </dl>
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<p><span class="comment">Categories</span></p>
+
+<p>{{ languages( { "ja": "ja/Extensions/Thunderbird" } ) }}</p>